diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ef922b6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 2.8) + +project(SensorKinect) + +# Options +# ------- +option(CREATE_TEST_BUILD "Create a test build which you do no have to install" OFF) +option(CREATE_OF_BUILD "Create a build for the ofxOpenNI addon" OFF) + +# Check the system +# ---------------- +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(SENSOR_PLATFORM_LINUX true) +elseif(WIN32) + set(SENSOR_PLATFORM_WIN32 true) +elseif(APPLE) + set(SENSOR_PLATFORM_MAC true) +endif() + +# Some global variables +# --------------------- +# @todo create find modules for openni! +if(CREATE_TEST_BUILD) + set(OPENNI_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI/") + set(OPENNI_NIMCODECS_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_TEST/lib/libnimCodecs.dylib") + set(OPENNI_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_TEST/lib/libOpenNI.dylib") + set(LIBJPEG_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_TEST/lib/libJPEG.dylib") + set(OPENNI_NIMCODECS_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_TEST/lib/libnimCodecs.dylib") + + # set the install paths for libraries and binaries + # ------------------------------------------------ + set(INSTALL_NAME_VALUE "@executable_path/../lib") + set(LIB_INSTALL_PATH "./lib/") + set(BIN_INSTALL_PATH "./bin/") + set(INCLUDE_FILES_INSTALL_PATH "include/") +elseif(CREATE_OF_BUILD) + set(OF_OPENNI_DATA_DIR "../../../data/openni/") + #set(OF_OPENNI_DATA_DIR "./../../../../../../../addons/ofxOpenNI/") + set(OPENNI_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI/") + set(OPENNI_NIMCODECS_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_openFrameworks/openni/lib/libnimCodecs.dylib") + set(OPENNI_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_openFrameworks/openni/lib/libOpenNI.dylib") + set(LIBJPEG_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_openFrameworks/openni/lib/libJPEG.dylib") + set(OPENNI_NIMCODECS_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/../OpenNI_openFrameworks/openni/lib/libnimCodecs.dylib") + + # set the install paths for libraries and binaries + # ------------------------------------------------ + #set(INSTALL_NAME_VALUE "@executable_path/${OF_OPENNI_DATA_DIR}lib/osx") + set(INSTALL_NAME_VALUE "@executable_path/${OF_OPENNI_DATA_DIR}lib") + set(LIB_INSTALL_PATH "./openni/lib/") + set(BIN_INSTALL_PATH "./bin/") + set(INCLUDE_FILES_INSTALL_PATH "include/") + set(CMAKE_OSX_ARCHITECTURES "i386;x86_64") +endif() + +set(XNCORE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include/") +set(XNCORE_LIB_NAME "XnCore") +set(XNDDK_LIB_NAME "XnDDK") +set(XNFORMAT_LIB_NAME "XnFormats") +set(XNDEVICEFILE_LIB_NAME "XnDeviceFile") +set(XNDEVICESENSOR_LIB_NAME "XnDevicesSensorV2") +set(XNSENSORSERVER_TARGET_NAME "XnSensorServer") +set(OPENNI_INCLUDE_DIR "${OPENNI_BASE_DIR}/Include/") +set(OPENNI_LIB_DIR "${OPENNI_BASE_DIR}/Platform/Mac/Bin/Release/") +set(LIBJPEG_INCLUDE_DIR "${OPENNI_BASE_DIR}/Source/External/LibJPEG/") + + +# Add the sub-cmakefiles.txt +# -------------------------- +add_subdirectory("./Source/XnCore/") +add_subdirectory("./Source/XnFormats/") +add_subdirectory("./Source/XnDDK/") +add_subdirectory("./Source/XnDeviceFile/") +add_subdirectory("./Source/XnDeviceSensorV2/") +add_subdirectory("./Source/Utils/XnSensorServer/") diff --git a/Include/XnEE/XnVSkeleton.h b/Include/XnEE/XnVSkeleton.h index 246a20f..318b631 100644 --- a/Include/XnEE/XnVSkeleton.h +++ b/Include/XnEE/XnVSkeleton.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef XNV_SKELETON_H -#define XNV_SKELETON_H - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * A skeleton is comprised of a head, a torso and 2 hands. - * It also holds a labeled object that describes it. - */ - -class XN_EE_FW_API XnVSkeleton -{ -public: - XnVSkeleton() - {} - XnVSkeleton(const XnVSkeleton& other) - { - m_Head = other.m_Head; - m_Torso = other.m_Torso; - m_RightHand = other.m_RightHand; - m_LeftHand = other.m_LeftHand; - } - - const XnVHead& Head() const - {return m_Head;} - XnVHead& Head() - {return m_Head;} - - const XnVTorso& Torso() const - {return m_Torso;} - XnVTorso& Torso() - {return m_Torso;} - - const XnVHand& RightHand() const - {return m_RightHand;} - XnVHand& RightHand() - {return m_RightHand;} - - const XnVHand& LeftHand() const - {return m_LeftHand;} - XnVHand& LeftHand() - {return m_LeftHand;} - - const XnVLabeledObject& LabeledObject() const - {return m_LabeledObject;} - XnVLabeledObject& LabeledObject() - {return m_LabeledObject;} - -private: - XnVHead m_Head; - XnVTorso m_Torso; - XnVHand m_RightHand, m_LeftHand; - XnVLabeledObject m_LabeledObject; -}; - -#endif // XNV_SKELETON_H +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef XNV_SKELETON_H +#define XNV_SKELETON_H + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * A skeleton is comprised of a head, a torso and 2 hands. + * It also holds a labeled object that describes it. + */ + +class XN_EE_FW_API XnVSkeleton +{ +public: + XnVSkeleton() + {} + XnVSkeleton(const XnVSkeleton& other) + { + m_Head = other.m_Head; + m_Torso = other.m_Torso; + m_RightHand = other.m_RightHand; + m_LeftHand = other.m_LeftHand; + } + + const XnVHead& Head() const + {return m_Head;} + XnVHead& Head() + {return m_Head;} + + const XnVTorso& Torso() const + {return m_Torso;} + XnVTorso& Torso() + {return m_Torso;} + + const XnVHand& RightHand() const + {return m_RightHand;} + XnVHand& RightHand() + {return m_RightHand;} + + const XnVHand& LeftHand() const + {return m_LeftHand;} + XnVHand& LeftHand() + {return m_LeftHand;} + + const XnVLabeledObject& LabeledObject() const + {return m_LabeledObject;} + XnVLabeledObject& LabeledObject() + {return m_LabeledObject;} + +private: + XnVHead m_Head; + XnVTorso m_Torso; + XnVHand m_RightHand, m_LeftHand; + XnVLabeledObject m_LabeledObject; +}; + +#endif // XNV_SKELETON_H diff --git a/Include/XnEE/XnVSphere.h b/Include/XnEE/XnVSphere.h index d99083b..485fbfd 100644 --- a/Include/XnEE/XnVSphere.h +++ b/Include/XnEE/XnVSphere.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_SPHERE_H_ -#define _XNV_SPHERE_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnV3DGeometry.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * This is a specific XnVVirtualObject class, which represents a Real World 3D sphere. - */ - -class XN_EE_FW_API XnVSphere : public XnV3DGeometry -{ -public: - XnVSphere(); - XnVSphere(const XnVPoint& ptCenter, XnUInt32 nRadius); - - void SetAttributes(const XnVPoint& ptCenter, XnUInt32 nRadius); - - /** - * Intersect the box with a depth map, resulting in the intersection depth map. - * - * @param [in] dmOther The depth map to check against - * @param [out] dmOutput The result of the intersection - */ - XnUInt32 Intersect(const XnVDepthMap& dmOther, XnVDepthMap& dmOutput); - /** - * Check if there is an intersection between the box and the depth map, - * With a minimum size. - * - * @param [in] dmOther The depth map to check against - * @param [in] nThreshold The minimum number of points in order to conclude an intersection - * - * @return true if the intersection had at least the minimum number of point. - */ - XnBool IsIntersect(const XnVDepthMap& dmOther, XnUInt32 nThreshold); - - XnBool IsIntersect(const XnV3DVector& pt) const; - /** - * Get the intersection size - * - * @param [in] dmOther The depth map to check against. - * - * @return Number of points in the intersection. - */ - XnUInt32 IntersectionSize(const XnVDepthMap& dmOther); - - inline XnBool IsValid() - { - return m_bValid; - } - -protected: - XnBool m_bValid; - XnUInt32 m_nRadius; -protected: - XnUInt32 Intersection(const XnVDepthMap& dmOther, XnUInt32 nThreshold, XnVDepthMap* pdmOutput); - -}; - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_SPHERE_H_ +#define _XNV_SPHERE_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnV3DGeometry.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * This is a specific XnVVirtualObject class, which represents a Real World 3D sphere. + */ + +class XN_EE_FW_API XnVSphere : public XnV3DGeometry +{ +public: + XnVSphere(); + XnVSphere(const XnVPoint& ptCenter, XnUInt32 nRadius); + + void SetAttributes(const XnVPoint& ptCenter, XnUInt32 nRadius); + + /** + * Intersect the box with a depth map, resulting in the intersection depth map. + * + * @param [in] dmOther The depth map to check against + * @param [out] dmOutput The result of the intersection + */ + XnUInt32 Intersect(const XnVDepthMap& dmOther, XnVDepthMap& dmOutput); + /** + * Check if there is an intersection between the box and the depth map, + * With a minimum size. + * + * @param [in] dmOther The depth map to check against + * @param [in] nThreshold The minimum number of points in order to conclude an intersection + * + * @return true if the intersection had at least the minimum number of point. + */ + XnBool IsIntersect(const XnVDepthMap& dmOther, XnUInt32 nThreshold); + + XnBool IsIntersect(const XnV3DVector& pt) const; + /** + * Get the intersection size + * + * @param [in] dmOther The depth map to check against. + * + * @return Number of points in the intersection. + */ + XnUInt32 IntersectionSize(const XnVDepthMap& dmOther); + + inline XnBool IsValid() + { + return m_bValid; + } + +protected: + XnBool m_bValid; + XnUInt32 m_nRadius; +protected: + XnUInt32 Intersection(const XnVDepthMap& dmOther, XnUInt32 nThreshold, XnVDepthMap* pdmOutput); + +}; + +#endif diff --git a/Include/XnEE/XnVStaticMap.h b/Include/XnEE/XnVStaticMap.h index aafede5..16f19b6 100644 --- a/Include/XnEE/XnVStaticMap.h +++ b/Include/XnEE/XnVStaticMap.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_STATIC_SHIFT_MAP_H_ -#define _XNV_STATIC_SHIFT_MAP_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnVGeneralStaticMap.h" -#include "XnVDepthMap.h" -#include "XnVDevice.h" - -/** - * This is a specific Static Map implementation, which implements XnVGeneralStaticMap. - * It uses a measure based on the noise of the depth values as a threshold. - * This value affects the depth differently in different depth values - the larger the depth, - * the larger the noise described by the same threshold. - */ - -class XN_EE_FW_API XnVStaticMap : public XnVGeneralStaticMap -{ -public: - XnVStaticMap(XnVDevice& Device, const XnChar* strINIFile = NULL); - ~XnVStaticMap(); - - /** - * Add a depth map to the static map. - * If previous static map existed and is in the same resolutions, the current depth map will be added. - * If previous static map existed and is in different resolutions, the current depth map will replace. - * - * @param [in] dmMap A depth map to add to the static. - */ - XnStatus AddMap(const XnVDepthMap& dmMap); - - /** - * This threshold is added as the noise relative to the depth in each pixel. - * The default value is 3. - * - * @param [in] nThreshold The new Shift Threshold - */ - void SetShiftThreshold(XnInt16 nThreshold); - XnInt16 GetShiftThreshold() const; - -protected: - /** - * Do specific things requires in this type of GeneralStaticMap when it is Reset. - */ - XnStatus DoReset(); - - XnStatus Init(XnUInt32 nNewSize); - XnDepthPixel DepthToNoise(XnDepthPixel nDepth, XnInt16 nShiftThreshold); - - XnBool CreateShiftToDepthTables(); - XnBool m_bAllocatedTables; - - XnUInt32* m_pAccumulationMap; - XnUInt16* m_pCounterMap; - - XnUInt16* m_pShiftToDepth; - XnUInt16* m_pDepthToShift; - XnVDevice* m_pCreatorDevice; - - XnInt16 m_nShiftThreshold; - - XnUInt32 m_nMaxDepth; -}; - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_STATIC_SHIFT_MAP_H_ +#define _XNV_STATIC_SHIFT_MAP_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnVGeneralStaticMap.h" +#include "XnVDepthMap.h" +#include "XnVDevice.h" + +/** + * This is a specific Static Map implementation, which implements XnVGeneralStaticMap. + * It uses a measure based on the noise of the depth values as a threshold. + * This value affects the depth differently in different depth values - the larger the depth, + * the larger the noise described by the same threshold. + */ + +class XN_EE_FW_API XnVStaticMap : public XnVGeneralStaticMap +{ +public: + XnVStaticMap(XnVDevice& Device, const XnChar* strINIFile = NULL); + ~XnVStaticMap(); + + /** + * Add a depth map to the static map. + * If previous static map existed and is in the same resolutions, the current depth map will be added. + * If previous static map existed and is in different resolutions, the current depth map will replace. + * + * @param [in] dmMap A depth map to add to the static. + */ + XnStatus AddMap(const XnVDepthMap& dmMap); + + /** + * This threshold is added as the noise relative to the depth in each pixel. + * The default value is 3. + * + * @param [in] nThreshold The new Shift Threshold + */ + void SetShiftThreshold(XnInt16 nThreshold); + XnInt16 GetShiftThreshold() const; + +protected: + /** + * Do specific things requires in this type of GeneralStaticMap when it is Reset. + */ + XnStatus DoReset(); + + XnStatus Init(XnUInt32 nNewSize); + XnDepthPixel DepthToNoise(XnDepthPixel nDepth, XnInt16 nShiftThreshold); + + XnBool CreateShiftToDepthTables(); + XnBool m_bAllocatedTables; + + XnUInt32* m_pAccumulationMap; + XnUInt16* m_pCounterMap; + + XnUInt16* m_pShiftToDepth; + XnUInt16* m_pDepthToShift; + XnVDevice* m_pCreatorDevice; + + XnInt16 m_nShiftThreshold; + + XnUInt32 m_nMaxDepth; +}; + +#endif diff --git a/Include/XnEE/XnVStatus.h b/Include/XnEE/XnVStatus.h index af8a256..f3f34a3 100644 --- a/Include/XnEE/XnVStatus.h +++ b/Include/XnEE/XnVStatus.h @@ -1,114 +1,114 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_STATUS_H_ -#define _XNV_STATUS_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_MASK_EE_CORE "EECore" - -#ifdef XN_EE_CORE_EXPORTS - #define XN_EE_CORE_API XN_API_EXPORT -#else - #define XN_EE_CORE_API XN_API_IMPORT -#endif - -#ifdef XN_EE_FW_EXPORTS - #define XN_EE_FW_API XN_API_EXPORT -#else - #define XN_EE_FW_API XN_API_IMPORT -#endif - -#ifdef XN_EE_MODULES_EXPORTS - #define XN_EE_MODULES_API XN_API_EXPORT -#else - #define XN_EE_MODULES_API XN_API_IMPORT -#endif - -#ifdef XN_USE_DEVICE_3_6 - #define XN_3_6_API - #define XN_3_6_PUBLIC_MEMBER public: -#else - #define XN_3_6_API XN_API_DEPRECATED("This is old 3.6 API. Please don't use it anymore") - #define XN_3_6_PUBLIC_MEMBER private: -#endif - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -XN_PS_STATUS_MESSAGE_MAP_START(XN_ERROR_GROUP_EE_CORE) -XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_INITIALIZED, "Device was not initialized!") -XN_STATUS_MESSAGE(XN_STATUS_EE_RESOLUTION_ILLEGAL, "Invalid resolution!") -XN_STATUS_MESSAGE(XN_STATUS_EE_RESOLUTION_MISMATCH, "Resolutions do not match!") -XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_ENOUGH_INFORMATION, "Not enough information!") -XN_STATUS_MESSAGE(XN_STATUS_EE_ILLEGAL_INPUT, "Illegal input!") -XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_ENOUGH_MEMORY, "Not enough memory!") -XN_STATUS_MESSAGE(XN_STATUS_EE_WRONG_DEVICE, "Wrong device!") -XN_STATUS_MESSAGE(XN_STATUS_EE_PARTIAL_SUCCESS, "Operation succeeded partially!") -XN_STATUS_MESSAGE(XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY, "This functionality is not supported!") -XN_STATUS_MESSAGE(XN_STATUS_EE_BAD_PARAMETER, "Bad parameter!") -XN_STATUS_MESSAGE(XN_STATUS_EE_ERROR, "Error!") -XN_STATUS_MESSAGE(XN_STATUS_EE_MATRIX_NOT_SYMMETRIC, "Matrix must be symmetric for this operation") -XN_PS_STATUS_MESSAGE_MAP_END(XN_ERROR_GROUP_EE_CORE) - -//--------------------------------------------------------------------------- -// Backwards compatibility -//--------------------------------------------------------------------------- -#ifndef XN_MESSAGE_MAP_REGISTER - -typedef XnStatus XN_API_DEPRECATED("Please use XnStatus instead.") XnVStatus; - -#define DECLARE_DEPRECATED_XNV_STATUS(xnv, xn) \ - const XnStatus XN_API_DEPRECATED("Please use " #xn " instead.") xnv = xn; - -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_OK, XN_STATUS_OK); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_INITIALIZED, XN_STATUS_EE_NOT_INITIALIZED); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_RESOLUTION_ILLEGAL, XN_STATUS_EE_RESOLUTION_ILLEGAL); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_RESOLUTION_MISMATCH, XN_STATUS_EE_RESOLUTION_MISMATCH); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_ENOUGH_INFORMATION, XN_STATUS_EE_NOT_ENOUGH_INFORMATION); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_ILLEGAL_INPUT, XN_STATUS_EE_ILLEGAL_INPUT); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_ENOUGH_MEMORY, XN_STATUS_EE_NOT_ENOUGH_MEMORY); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_WRONG_DEVICE, XN_STATUS_EE_WRONG_DEVICE); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_PATRIAL_SUCCESS, XN_STATUS_EE_PARTIAL_SUCCESS); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_UNSUPPORTED_FUNCITONALITY, XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_BAD_PARAMETER, XN_STATUS_EE_BAD_PARAMETER); -DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_ERROR, XN_STATUS_EE_ERROR); -DECLARE_DEPRECATED_XNV_STATUS(XN_STATUS_EE_UNSUPPORTED_FUNCITONALITY, XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY); - -#endif - -#endif // _XNV_STATUS_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_STATUS_H_ +#define _XNV_STATUS_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MASK_EE_CORE "EECore" + +#ifdef XN_EE_CORE_EXPORTS + #define XN_EE_CORE_API XN_API_EXPORT +#else + #define XN_EE_CORE_API XN_API_IMPORT +#endif + +#ifdef XN_EE_FW_EXPORTS + #define XN_EE_FW_API XN_API_EXPORT +#else + #define XN_EE_FW_API XN_API_IMPORT +#endif + +#ifdef XN_EE_MODULES_EXPORTS + #define XN_EE_MODULES_API XN_API_EXPORT +#else + #define XN_EE_MODULES_API XN_API_IMPORT +#endif + +#ifdef XN_USE_DEVICE_3_6 + #define XN_3_6_API + #define XN_3_6_PUBLIC_MEMBER public: +#else + #define XN_3_6_API XN_API_DEPRECATED("This is old 3.6 API. Please don't use it anymore") + #define XN_3_6_PUBLIC_MEMBER private: +#endif + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +XN_PS_STATUS_MESSAGE_MAP_START(XN_ERROR_GROUP_EE_CORE) +XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_INITIALIZED, "Device was not initialized!") +XN_STATUS_MESSAGE(XN_STATUS_EE_RESOLUTION_ILLEGAL, "Invalid resolution!") +XN_STATUS_MESSAGE(XN_STATUS_EE_RESOLUTION_MISMATCH, "Resolutions do not match!") +XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_ENOUGH_INFORMATION, "Not enough information!") +XN_STATUS_MESSAGE(XN_STATUS_EE_ILLEGAL_INPUT, "Illegal input!") +XN_STATUS_MESSAGE(XN_STATUS_EE_NOT_ENOUGH_MEMORY, "Not enough memory!") +XN_STATUS_MESSAGE(XN_STATUS_EE_WRONG_DEVICE, "Wrong device!") +XN_STATUS_MESSAGE(XN_STATUS_EE_PARTIAL_SUCCESS, "Operation succeeded partially!") +XN_STATUS_MESSAGE(XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY, "This functionality is not supported!") +XN_STATUS_MESSAGE(XN_STATUS_EE_BAD_PARAMETER, "Bad parameter!") +XN_STATUS_MESSAGE(XN_STATUS_EE_ERROR, "Error!") +XN_STATUS_MESSAGE(XN_STATUS_EE_MATRIX_NOT_SYMMETRIC, "Matrix must be symmetric for this operation") +XN_PS_STATUS_MESSAGE_MAP_END(XN_ERROR_GROUP_EE_CORE) + +//--------------------------------------------------------------------------- +// Backwards compatibility +//--------------------------------------------------------------------------- +#ifndef XN_MESSAGE_MAP_REGISTER + +typedef XnStatus XN_API_DEPRECATED("Please use XnStatus instead.") XnVStatus; + +#define DECLARE_DEPRECATED_XNV_STATUS(xnv, xn) \ + const XnStatus XN_API_DEPRECATED("Please use " #xn " instead.") xnv = xn; + +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_OK, XN_STATUS_OK); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_INITIALIZED, XN_STATUS_EE_NOT_INITIALIZED); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_RESOLUTION_ILLEGAL, XN_STATUS_EE_RESOLUTION_ILLEGAL); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_RESOLUTION_MISMATCH, XN_STATUS_EE_RESOLUTION_MISMATCH); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_ENOUGH_INFORMATION, XN_STATUS_EE_NOT_ENOUGH_INFORMATION); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_ILLEGAL_INPUT, XN_STATUS_EE_ILLEGAL_INPUT); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_NOT_ENOUGH_MEMORY, XN_STATUS_EE_NOT_ENOUGH_MEMORY); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_WRONG_DEVICE, XN_STATUS_EE_WRONG_DEVICE); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_PATRIAL_SUCCESS, XN_STATUS_EE_PARTIAL_SUCCESS); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_UNSUPPORTED_FUNCITONALITY, XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_BAD_PARAMETER, XN_STATUS_EE_BAD_PARAMETER); +DECLARE_DEPRECATED_XNV_STATUS(XNV_STATUS_ERROR, XN_STATUS_EE_ERROR); +DECLARE_DEPRECATED_XNV_STATUS(XN_STATUS_EE_UNSUPPORTED_FUNCITONALITY, XN_STATUS_EE_UNSUPPORTED_FUNCTIONALITY); + +#endif + +#endif // _XNV_STATUS_H_ + diff --git a/Include/XnEE/XnVStream.h b/Include/XnEE/XnVStream.h index 1dff329..87dfa9d 100644 --- a/Include/XnEE/XnVStream.h +++ b/Include/XnEE/XnVStream.h @@ -1,58 +1,58 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_STREAM_H -#define _XNV_STREAM_H - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnVModule.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * A stream is a specific kind of module - one that has a buffer attached to it. - */ -class XN_EE_CORE_API XnVStream : public XnVModule -{ -public: - XnVStream(); - - XnStatus GetBuffer(void*& pBuffer) const; - XnStatus GetBufferSize(XnUInt32& nSize) const; - XnStatus GetBufferAllocatedSize(XnUInt32& nSize) const; - - XnStatus CopyFrom(const XnVStream& other, XnUInt64 nTimestamp = 0); - XnStatus CopyFrom(const void* pSource, XnUInt32 nDataSize, XnUInt64 nTimestamp = 0); -}; - -#endif // XNV_STREAM_H +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_STREAM_H +#define _XNV_STREAM_H + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnVModule.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * A stream is a specific kind of module - one that has a buffer attached to it. + */ +class XN_EE_CORE_API XnVStream : public XnVModule +{ +public: + XnVStream(); + + XnStatus GetBuffer(void*& pBuffer) const; + XnStatus GetBufferSize(XnUInt32& nSize) const; + XnStatus GetBufferAllocatedSize(XnUInt32& nSize) const; + + XnStatus CopyFrom(const XnVStream& other, XnUInt64 nTimestamp = 0); + XnStatus CopyFrom(const void* pSource, XnUInt32 nDataSize, XnUInt64 nTimestamp = 0); +}; + +#endif // XNV_STREAM_H diff --git a/Include/XnEE/XnVStreamContainer.h b/Include/XnEE/XnVStreamContainer.h index 9f7d978..179a433 100644 --- a/Include/XnEE/XnVStreamContainer.h +++ b/Include/XnEE/XnVStreamContainer.h @@ -1,84 +1,84 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_STREAM_CONTAINER_H_ -#define _XNV_STREAM_CONTAINER_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnVStatus.h" -#include "XnVPropertySet.h" -#include -#include "XnVEventHandlers.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * This is an interface for any class that holds Streams and Modules. - * Currently implemented a single subclass - XnVDevice. - */ -class XN_EE_CORE_API XnVStreamContainer -{ -public: - virtual ~XnVStreamContainer() {} - - virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64& nValue) const = 0; - virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble& fValue) const = 0; - - virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64 nValue) = 0; - virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble fValue) = 0; - - virtual XnStatus DoesModuleExist(const XnChar* strModule, XnBool* pbDoesExist) const = 0; - virtual XnStatus DoesPropertyExist(const XnChar* strModule, const XnChar* strProperty, XnBool* pbDoesExist) const = 0; - - virtual XnStatus GetAllProperties(XnVPropertySet& PropertySet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) const = 0; - - virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnChar* pcsValue) const = 0; - virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue) const = 0; - virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, const XnChar* csValue) = 0; - virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue) = 0; - - virtual XnStatus RegisterForPropertyChangedEvent(const XnChar* strModule, const XnChar* strProperty, XnVModulePropertyChangedHandler* pHandler, XnCallbackHandle* phCallback) = 0; - virtual XnStatus RegisterForStreamCollectionChangedEvent(XnVStreamCollectionChangedHandler* pHandler, XnCallbackHandle* phCallback) = 0; - virtual XnStatus UnregisterFromPropertyChangedEvent(const XnChar* strModule, const XnChar* strProperty, XnCallbackHandle hCallback) = 0; - virtual XnStatus UnregisterFromStreamCollectionChangedEvent(XnCallbackHandle hCallback) = 0; - - XN_3_6_API virtual XnBool IsModuleExist(const XnChar* strModule) = 0; - XN_3_6_API virtual XnBool IsPropertyExist(const XnChar* strModule, const XnChar* strProperty) = 0; - XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt16& nValue) const = 0; - XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt32& nValue) const = 0; - XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, void*& pValue) const = 0; - XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt16 nValue) = 0; - XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt32 nValue) = 0; - XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, void* pValue) = 0; -}; - -#endif // _XNV_STREAM_CONTAINER_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_STREAM_CONTAINER_H_ +#define _XNV_STREAM_CONTAINER_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnVStatus.h" +#include "XnVPropertySet.h" +#include +#include "XnVEventHandlers.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * This is an interface for any class that holds Streams and Modules. + * Currently implemented a single subclass - XnVDevice. + */ +class XN_EE_CORE_API XnVStreamContainer +{ +public: + virtual ~XnVStreamContainer() {} + + virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64& nValue) const = 0; + virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble& fValue) const = 0; + + virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64 nValue) = 0; + virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble fValue) = 0; + + virtual XnStatus DoesModuleExist(const XnChar* strModule, XnBool* pbDoesExist) const = 0; + virtual XnStatus DoesPropertyExist(const XnChar* strModule, const XnChar* strProperty, XnBool* pbDoesExist) const = 0; + + virtual XnStatus GetAllProperties(XnVPropertySet& PropertySet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) const = 0; + + virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnChar* pcsValue) const = 0; + virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue) const = 0; + virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, const XnChar* csValue) = 0; + virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue) = 0; + + virtual XnStatus RegisterForPropertyChangedEvent(const XnChar* strModule, const XnChar* strProperty, XnVModulePropertyChangedHandler* pHandler, XnCallbackHandle* phCallback) = 0; + virtual XnStatus RegisterForStreamCollectionChangedEvent(XnVStreamCollectionChangedHandler* pHandler, XnCallbackHandle* phCallback) = 0; + virtual XnStatus UnregisterFromPropertyChangedEvent(const XnChar* strModule, const XnChar* strProperty, XnCallbackHandle hCallback) = 0; + virtual XnStatus UnregisterFromStreamCollectionChangedEvent(XnCallbackHandle hCallback) = 0; + + XN_3_6_API virtual XnBool IsModuleExist(const XnChar* strModule) = 0; + XN_3_6_API virtual XnBool IsPropertyExist(const XnChar* strModule, const XnChar* strProperty) = 0; + XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt16& nValue) const = 0; + XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt32& nValue) const = 0; + XN_3_6_API virtual XnStatus GetProperty(const XnChar* strModule, const XnChar* strProperty, void*& pValue) const = 0; + XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt16 nValue) = 0; + XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt32 nValue) = 0; + XN_3_6_API virtual XnStatus SetProperty(const XnChar* strModule, const XnChar* strProperty, void* pValue) = 0; +}; + +#endif // _XNV_STREAM_CONTAINER_H_ diff --git a/Include/XnEE/XnVStreamData.h b/Include/XnEE/XnVStreamData.h index 19ad626..d7a9752 100644 --- a/Include/XnEE/XnVStreamData.h +++ b/Include/XnEE/XnVStreamData.h @@ -1,107 +1,107 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_V_STREAM_OUTPUT_H__ -#define __XN_V_STREAM_OUTPUT_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnVEventHandlers.h" -#include "XnVStream.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_EE_CORE_API XnVStreamData : private XnVModulePropertyChangedHandler -{ -public: - XnVStreamData(XnVStream* pStream = NULL, XnBool bIsLive = FALSE, XnBool bWaitForDataUpdate = FALSE); - virtual ~XnVStreamData(); - - XnStatus Initialize(const XnVStreamData& soOther); - - inline XnBool IsValid() const { return m_bValid; } - - inline XnVStream* GetStream() { return m_pStream; } - inline const XnVStream* GetStream() const { return m_pStream; } - - XnVStreamContainer* GetCreator(); - const XnVStreamContainer* GetCreator() const; - - inline XnBool IsLive() const { return m_bIsLive; } - - inline XnBool IsDataNew() const { return m_bIsNewData; } - inline XnUInt64 GetTimestamp() const { return m_nTimestamp; } - inline XnUInt32 GetFrameID() const { return m_nFrameID; } - inline XnUInt32 GetDataSize() const { return m_nDataSize; } - - XnStatus SetTimestamp(XnUInt64 nTimestamp); - XnStatus SetFrameID(XnUInt32 nFrameID); - XnStatus SetDataSize(XnUInt32 nDataSize); - XnStatus SetDataNew(XnBool bIsNew); - - inline void* Data() const { return m_pData; } - - XnStatus CopyFrom(const void* pData, XnUInt32 nDataSize, XnUInt64 nTimestamp = 0); - XnStatus CopyFrom(const XnVStreamData& sd, XnUInt64 nTimestamp = 0); - -protected: - friend class XnVDeviceStream; - XnStatus UnderlyingStreamUpdated(); - virtual XnStatus ReadPropertiesFromStream(); - XnStatus AddWatchedProperty(const XnChar* strProp); - - inline void SetValidity(XnBool bValid) { m_bValid = bValid; } - -private: - void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty); - - typedef struct XnWatchedProperty - { - const XnChar* strName; - XnCallbackHandle hCallback; - } XnWatchedProperty; - - XN_DECLARE_LIST_DECL(XN_EE_CORE_API, XnWatchedProperty, XnWatchedPropertiesList) - - XnBool m_bIsLive; - XnBool m_bWaitForDataUpdate; - XnWatchedPropertiesList m_WatchedProperties; - XnBool m_bChangeOccurred; - - XN_3_6_PUBLIC_MEMBER XnVStream* m_pStream; - XN_3_6_PUBLIC_MEMBER XnBool m_bValid; - - XnBool m_bIsNewData; - XnUInt64 m_nTimestamp; - XnUInt32 m_nFrameID; - void* m_pData; - XnUInt32 m_nDataSize; -}; - -#endif //__XN_V_STREAM_OUTPUT_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_V_STREAM_OUTPUT_H__ +#define __XN_V_STREAM_OUTPUT_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnVEventHandlers.h" +#include "XnVStream.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_EE_CORE_API XnVStreamData : private XnVModulePropertyChangedHandler +{ +public: + XnVStreamData(XnVStream* pStream = NULL, XnBool bIsLive = FALSE, XnBool bWaitForDataUpdate = FALSE); + virtual ~XnVStreamData(); + + XnStatus Initialize(const XnVStreamData& soOther); + + inline XnBool IsValid() const { return m_bValid; } + + inline XnVStream* GetStream() { return m_pStream; } + inline const XnVStream* GetStream() const { return m_pStream; } + + XnVStreamContainer* GetCreator(); + const XnVStreamContainer* GetCreator() const; + + inline XnBool IsLive() const { return m_bIsLive; } + + inline XnBool IsDataNew() const { return m_bIsNewData; } + inline XnUInt64 GetTimestamp() const { return m_nTimestamp; } + inline XnUInt32 GetFrameID() const { return m_nFrameID; } + inline XnUInt32 GetDataSize() const { return m_nDataSize; } + + XnStatus SetTimestamp(XnUInt64 nTimestamp); + XnStatus SetFrameID(XnUInt32 nFrameID); + XnStatus SetDataSize(XnUInt32 nDataSize); + XnStatus SetDataNew(XnBool bIsNew); + + inline void* Data() const { return m_pData; } + + XnStatus CopyFrom(const void* pData, XnUInt32 nDataSize, XnUInt64 nTimestamp = 0); + XnStatus CopyFrom(const XnVStreamData& sd, XnUInt64 nTimestamp = 0); + +protected: + friend class XnVDeviceStream; + XnStatus UnderlyingStreamUpdated(); + virtual XnStatus ReadPropertiesFromStream(); + XnStatus AddWatchedProperty(const XnChar* strProp); + + inline void SetValidity(XnBool bValid) { m_bValid = bValid; } + +private: + void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty); + + typedef struct XnWatchedProperty + { + const XnChar* strName; + XnCallbackHandle hCallback; + } XnWatchedProperty; + + XN_DECLARE_LIST_DECL(XN_EE_CORE_API, XnWatchedProperty, XnWatchedPropertiesList) + + XnBool m_bIsLive; + XnBool m_bWaitForDataUpdate; + XnWatchedPropertiesList m_WatchedProperties; + XnBool m_bChangeOccurred; + + XN_3_6_PUBLIC_MEMBER XnVStream* m_pStream; + XN_3_6_PUBLIC_MEMBER XnBool m_bValid; + + XnBool m_bIsNewData; + XnUInt64 m_nTimestamp; + XnUInt32 m_nFrameID; + void* m_pData; + XnUInt32 m_nDataSize; +}; + +#endif //__XN_V_STREAM_OUTPUT_H__ diff --git a/Include/XnEE/XnVTorso.h b/Include/XnEE/XnVTorso.h index 9f88cd4..2ac0e1f 100644 --- a/Include/XnEE/XnVTorso.h +++ b/Include/XnEE/XnVTorso.h @@ -1,70 +1,70 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef XNV_TORSO_H -#define XNV_TORSO_H - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * A torso is a body part that has a front vector and an up vector. - */ - -class XN_EE_FW_API XnVTorso : public XnVBodyPart -{ -public: - XnVTorso() - {} - XnVTorso(const XnVTorso& other) - { - m_FrontVector = other.m_FrontVector; - m_UpVector = other.m_UpVector; - } - - const XnV3DVector& FrontVector() const - {return m_FrontVector;} - XnV3DVector& FrontVector() - {return m_FrontVector;} - - const XnV3DVector& UpVector() const - {return m_UpVector;} - XnV3DVector& UpVector() - {return m_UpVector;} -protected: - XnV3DVector m_FrontVector, m_UpVector; - -}; - -#endif // XNV_TORSO_H +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef XNV_TORSO_H +#define XNV_TORSO_H + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * A torso is a body part that has a front vector and an up vector. + */ + +class XN_EE_FW_API XnVTorso : public XnVBodyPart +{ +public: + XnVTorso() + {} + XnVTorso(const XnVTorso& other) + { + m_FrontVector = other.m_FrontVector; + m_UpVector = other.m_UpVector; + } + + const XnV3DVector& FrontVector() const + {return m_FrontVector;} + XnV3DVector& FrontVector() + {return m_FrontVector;} + + const XnV3DVector& UpVector() const + {return m_UpVector;} + XnV3DVector& UpVector() + {return m_UpVector;} +protected: + XnV3DVector m_FrontVector, m_UpVector; + +}; + +#endif // XNV_TORSO_H diff --git a/Include/XnEE/XnVUpscale.h b/Include/XnEE/XnVUpscale.h index 5e8bddf..d6135e4 100644 --- a/Include/XnEE/XnVUpscale.h +++ b/Include/XnEE/XnVUpscale.h @@ -1,83 +1,83 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_UPSCALE_H_ -#define _XNV_UPSCALE_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnVDepthMap.h" -#include "XnVImageMap.h" -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * Upscale an XnVDepthMap instance. - * Scaling is done in powers of 2, and is done by using the depth from a certain pixel - * and copying it to the entire nxn depth box, where n is the scale factor. - */ -class XN_EE_FW_API XnVUpscale -{ -public: - /** - * Upscale methods: - * MULTIPLY - use the same value for entire upscaled 2nx2n - * GRADUAL - use a gradiant of neighbors. Not Supported. - */ - typedef enum - { - XNV_USM_MULTIPLY, - XNV_USM_GRADUAL, - XNV_USM_UNKNOWN - } XnVUpscaleMethod; - - XnVUpscale() - {} - /** - * Upscale a depth map in a factor (which must be a power of 2). - * - * @param [in] dmOrigMap The original depth map - * @param [out] dmNewMap The upscaled depth map - * @param [in] nFactor The factor by which to scale - * @param [in] eUMethod The scale method. XNV_USM_MULTIPLY is the only one implemented. - */ - XnStatus Run(const XnVDepthMap& dmOrigMap, XnVDepthMap& dmNewMap, XnUInt16 nFactor, XnVUpscaleMethod eUMethod); - -protected: - XnStatus GetShiftSize(XnUInt16 nFactor, XnInt8& nShiftSize) const; - - XnStatus UseOne(const XnVDepthMap& dmOrigMap, XnVDepthMap& dmNewMap, XnUInt8 nShiftSize); -}; - -#endif //_XNV_UPSCALE_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_UPSCALE_H_ +#define _XNV_UPSCALE_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnVDepthMap.h" +#include "XnVImageMap.h" +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * Upscale an XnVDepthMap instance. + * Scaling is done in powers of 2, and is done by using the depth from a certain pixel + * and copying it to the entire nxn depth box, where n is the scale factor. + */ +class XN_EE_FW_API XnVUpscale +{ +public: + /** + * Upscale methods: + * MULTIPLY - use the same value for entire upscaled 2nx2n + * GRADUAL - use a gradiant of neighbors. Not Supported. + */ + typedef enum + { + XNV_USM_MULTIPLY, + XNV_USM_GRADUAL, + XNV_USM_UNKNOWN + } XnVUpscaleMethod; + + XnVUpscale() + {} + /** + * Upscale a depth map in a factor (which must be a power of 2). + * + * @param [in] dmOrigMap The original depth map + * @param [out] dmNewMap The upscaled depth map + * @param [in] nFactor The factor by which to scale + * @param [in] eUMethod The scale method. XNV_USM_MULTIPLY is the only one implemented. + */ + XnStatus Run(const XnVDepthMap& dmOrigMap, XnVDepthMap& dmNewMap, XnUInt16 nFactor, XnVUpscaleMethod eUMethod); + +protected: + XnStatus GetShiftSize(XnUInt16 nFactor, XnInt8& nShiftSize) const; + + XnStatus UseOne(const XnVDepthMap& dmOrigMap, XnVDepthMap& dmNewMap, XnUInt8 nShiftSize); +}; + +#endif //_XNV_UPSCALE_H_ + diff --git a/Include/XnEE/XnVUserExtractor.h b/Include/XnEE/XnVUserExtractor.h index 13ec360..bf7aeb8 100644 --- a/Include/XnEE/XnVUserExtractor.h +++ b/Include/XnEE/XnVUserExtractor.h @@ -1,205 +1,205 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_USER_EXTRACTOR_H_ -#define _XNV_USER_EXTRACTOR_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnVDepthMap.h" -#include "XnVRealObject.h" -#include "XnVLabelMatrix.h" - -#include "XnVBoundingBox.h" - -#include "XnVPointContainer.h" -#include "XnVConnectedComponentDetector.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define MAX_CCS 2000 -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * This algorithm uses as input a XnVDepthMap instance and an XnVLabelMatrix, - * which may be the output of XnVConnectedComponentDetector. - * The XnVLabelMatrix can be either supplied by the user - * or XnVConnectedComponentDetector is performed internally. - * The algorithm takes the Connected Component which is closest and large enough - * (threshold exists to determine what "large enough" means"), determines this is - * the basis of the User, and adds all other Connected Components which are - * closer than it, or have some overlap with it (another threshold). - */ - -class XN_EE_FW_API XnVUserExtractor -{ -public: - XnVUserExtractor(); - ~XnVUserExtractor(); - - /** - * Extracts a user from the depth map, putting the result in a XnVRealObject object supplied. - * A Label Matrix is supplied, created externally. - * - * @param [in] dmMap the depth map to work on. - * @param [in] lmLabels the label matrix, the output of the XnVConnectedComponentDetector - * @param [in,out] roUser The user in which to put the output. - * @param [in] bKeep Should keep the user extracted. False means to have all the scene except for it. - */ - XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels, XnVRealObject& roUser, XnBool bKeep = true) - { - return Run(dmMap, lmLabels, roUser.GetDepthMap(), bKeep); - } - - /** - * Extracts a user from the depth map, leaving only it in the original depth map. - * A Label Matrix is supplied, created externally. - * - * @param [in,out] dmMap the depth map to start from. On success, it will contain only the user. - * @param [in] lmLabels The label matrix, the output of the XnVConenctedComponentDetector - */ - XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels) - { - return Run(dmMap, lmLabels, NULL, true); - } - - /** - * Extracts a user from the depth map, putting the result in a XnVRealObject object supplied. - * - * @param [in] dmMap the depth map to work on. - * @param [in,out] roUser The user in which to put the output. - * @param [in] bKeep Should keep the user extracted. False means to have all the scene except for it. - */ - XnStatus Run(XnVDepthMap& dmMap, XnVRealObject& roUser, XnBool bKeep = true) - { - XnStatus rc; - - rc = CreateLabels(dmMap); - if (rc != XN_STATUS_OK) - return rc; - - return Run(dmMap, *m_pLabels, roUser, bKeep); - } - /** - * Extracts a user from the depth map, leaving only it in the original depth map. - * - * @param [in,out] dmMap the depth map to start from. On success, it will contain only the user. - */ - XnStatus Run(XnVDepthMap& dmMap) - { - XnStatus rc; - - rc = CreateLabels(dmMap); - if (rc != XN_STATUS_OK) - return rc; - - return Run(dmMap, *m_pLabels); - } - - /** - * MinSizeRatioToChoose determines the minimal size of chosen connected component. - * The chosen connected component is the closest one that is at least the proper size. - * The size used is the total amount of pixels divided by this parameter. - * For instance, if the full resolution is 640x480, and the threshold is set to 32, - * then the minimal size a connected component must be to be considered large enough - * is (640*480)/32 = 9600 pixels. - * The default value is 32. - * - * @param [in] nMinSizeRatioToChoose - */ - void SetMinSizeRatioToChoose(XnUInt32 nMinSizeRatioToChoose) - { - m_nMinSizeRatioToChoose = nMinSizeRatioToChoose; - } - XnUInt32 GetMinSizeRatioToChoose() const - { - return m_nMinSizeRatioToChoose; - } - - /** - * DepthOverlap determines the minimal overlap in depth that a connected component has to have - * with the chosen connected component, in order to be a candidate to join it as the user. - * For instance, a depth overlap threshold of 1 means any connected component with at least - * one pixel closer by 1 than the maximal depth of the chosen connected component is added to the user. - * Smaller values will cause further connected components to be added. - * The default value is 0. - * - * @param [in] nDepthOverlap - */ - void SetDepthOverlap(XnInt32 nDepthOverlap) - { - m_nDepthOverlap = nDepthOverlap; - } - XnInt32 GetDepthOverlap() const - { - return m_nDepthOverlap; - } - - /** - * UseUserBoundingBox is used after a connected component is chosen. - * If it is true, then all other connected components that don't have any pixel - * in the chosen one's bounding box will not be considered to be part of the user. - * The default value is false. - * - * @param [in] bUseUserBoundingBox - */ - void SetUseUserBoundingBox(XnBool bUseUserBoundingBox) - { - m_bUseUserBoundingBox = bUseUserBoundingBox; - } - XnBool GetUseUserBoundingBox() const - { - return m_bUseUserBoundingBox; - } - -protected: - XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels, XnVDepthMap* dmOutput, XnBool bKeep); - XnStatus GetCCs(const XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels1, - XnUInt16 nMinX, XnUInt16 nMaxX, XnUInt16 nMinY, XnUInt16 nMaxY); - - XnStatus InitializeLabels(); - XnStatus CreateLabels(XnVDepthMap& dmMap); - - XnVBoundingBox m_CCs[MAX_CCS]; - - XnVDepthMap m_dmWorkingMap; - XnUInt32 m_nMinSizeRatioToChoose; - XnInt32 m_nDepthOverlap; - - XnBool m_bUseUserBoundingBox; - - XnVConnectedComponentDetector* m_pagLabeler; - XnVLabelMatrix* m_pLabels; -}; - - -#endif //_XNV_USER_EXTRACTOR_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_USER_EXTRACTOR_H_ +#define _XNV_USER_EXTRACTOR_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnVDepthMap.h" +#include "XnVRealObject.h" +#include "XnVLabelMatrix.h" + +#include "XnVBoundingBox.h" + +#include "XnVPointContainer.h" +#include "XnVConnectedComponentDetector.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define MAX_CCS 2000 +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * This algorithm uses as input a XnVDepthMap instance and an XnVLabelMatrix, + * which may be the output of XnVConnectedComponentDetector. + * The XnVLabelMatrix can be either supplied by the user + * or XnVConnectedComponentDetector is performed internally. + * The algorithm takes the Connected Component which is closest and large enough + * (threshold exists to determine what "large enough" means"), determines this is + * the basis of the User, and adds all other Connected Components which are + * closer than it, or have some overlap with it (another threshold). + */ + +class XN_EE_FW_API XnVUserExtractor +{ +public: + XnVUserExtractor(); + ~XnVUserExtractor(); + + /** + * Extracts a user from the depth map, putting the result in a XnVRealObject object supplied. + * A Label Matrix is supplied, created externally. + * + * @param [in] dmMap the depth map to work on. + * @param [in] lmLabels the label matrix, the output of the XnVConnectedComponentDetector + * @param [in,out] roUser The user in which to put the output. + * @param [in] bKeep Should keep the user extracted. False means to have all the scene except for it. + */ + XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels, XnVRealObject& roUser, XnBool bKeep = true) + { + return Run(dmMap, lmLabels, roUser.GetDepthMap(), bKeep); + } + + /** + * Extracts a user from the depth map, leaving only it in the original depth map. + * A Label Matrix is supplied, created externally. + * + * @param [in,out] dmMap the depth map to start from. On success, it will contain only the user. + * @param [in] lmLabels The label matrix, the output of the XnVConenctedComponentDetector + */ + XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels) + { + return Run(dmMap, lmLabels, NULL, true); + } + + /** + * Extracts a user from the depth map, putting the result in a XnVRealObject object supplied. + * + * @param [in] dmMap the depth map to work on. + * @param [in,out] roUser The user in which to put the output. + * @param [in] bKeep Should keep the user extracted. False means to have all the scene except for it. + */ + XnStatus Run(XnVDepthMap& dmMap, XnVRealObject& roUser, XnBool bKeep = true) + { + XnStatus rc; + + rc = CreateLabels(dmMap); + if (rc != XN_STATUS_OK) + return rc; + + return Run(dmMap, *m_pLabels, roUser, bKeep); + } + /** + * Extracts a user from the depth map, leaving only it in the original depth map. + * + * @param [in,out] dmMap the depth map to start from. On success, it will contain only the user. + */ + XnStatus Run(XnVDepthMap& dmMap) + { + XnStatus rc; + + rc = CreateLabels(dmMap); + if (rc != XN_STATUS_OK) + return rc; + + return Run(dmMap, *m_pLabels); + } + + /** + * MinSizeRatioToChoose determines the minimal size of chosen connected component. + * The chosen connected component is the closest one that is at least the proper size. + * The size used is the total amount of pixels divided by this parameter. + * For instance, if the full resolution is 640x480, and the threshold is set to 32, + * then the minimal size a connected component must be to be considered large enough + * is (640*480)/32 = 9600 pixels. + * The default value is 32. + * + * @param [in] nMinSizeRatioToChoose + */ + void SetMinSizeRatioToChoose(XnUInt32 nMinSizeRatioToChoose) + { + m_nMinSizeRatioToChoose = nMinSizeRatioToChoose; + } + XnUInt32 GetMinSizeRatioToChoose() const + { + return m_nMinSizeRatioToChoose; + } + + /** + * DepthOverlap determines the minimal overlap in depth that a connected component has to have + * with the chosen connected component, in order to be a candidate to join it as the user. + * For instance, a depth overlap threshold of 1 means any connected component with at least + * one pixel closer by 1 than the maximal depth of the chosen connected component is added to the user. + * Smaller values will cause further connected components to be added. + * The default value is 0. + * + * @param [in] nDepthOverlap + */ + void SetDepthOverlap(XnInt32 nDepthOverlap) + { + m_nDepthOverlap = nDepthOverlap; + } + XnInt32 GetDepthOverlap() const + { + return m_nDepthOverlap; + } + + /** + * UseUserBoundingBox is used after a connected component is chosen. + * If it is true, then all other connected components that don't have any pixel + * in the chosen one's bounding box will not be considered to be part of the user. + * The default value is false. + * + * @param [in] bUseUserBoundingBox + */ + void SetUseUserBoundingBox(XnBool bUseUserBoundingBox) + { + m_bUseUserBoundingBox = bUseUserBoundingBox; + } + XnBool GetUseUserBoundingBox() const + { + return m_bUseUserBoundingBox; + } + +protected: + XnStatus Run(XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels, XnVDepthMap* dmOutput, XnBool bKeep); + XnStatus GetCCs(const XnVDepthMap& dmMap, const XnVLabelMatrix& lmLabels1, + XnUInt16 nMinX, XnUInt16 nMaxX, XnUInt16 nMinY, XnUInt16 nMaxY); + + XnStatus InitializeLabels(); + XnStatus CreateLabels(XnVDepthMap& dmMap); + + XnVBoundingBox m_CCs[MAX_CCS]; + + XnVDepthMap m_dmWorkingMap; + XnUInt32 m_nMinSizeRatioToChoose; + XnInt32 m_nDepthOverlap; + + XnBool m_bUseUserBoundingBox; + + XnVConnectedComponentDetector* m_pagLabeler; + XnVLabelMatrix* m_pLabels; +}; + + +#endif //_XNV_USER_EXTRACTOR_H_ + diff --git a/Include/XnEE/XnVVirtualObject.h b/Include/XnEE/XnVVirtualObject.h index a15bd05..0b23092 100644 --- a/Include/XnEE/XnVVirtualObject.h +++ b/Include/XnEE/XnVVirtualObject.h @@ -1,100 +1,100 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XNV_VIRTUAL_OBJECT_H_ -#define _XNV_VIRTUAL_OBJECT_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnVObject.h" -#include "XnVDepthMap.h" -#include "XnVBoundingBox.h" -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** - * XnVVirtualObject is a base class for all user-created objects that are inserted - * into the scene. - * Each of these objects must be able to intersect with a XnVDepthMap. - * The intersection is in Real World coordinations. - * Currently implemented virtual objects include XnV3DBox and XnVSphere. - */ - -class XN_EE_FW_API XnVVirtualObject : public XnVObject -{ -public: - XnVVirtualObject(); - - virtual ~XnVVirtualObject() {} - - /** - * Intersect the virtual object with the depth map. - * Intersection is done in Real World coordinations. - * Adds the pixels from the input depth map that are inside or on the virtual object - * to the output depth map. - * No pixels are deleted from the output depth map if they already exist. - * - * @param [in] dmOther The input depth map on which to run. - * @param [in,out] dmOutput The output depth map, with only the pixels inside or on the virtual object. - */ - virtual XnUInt32 Intersect(const XnVDepthMap& dmOther, XnVDepthMap& dmOutput) = 0; - /** - * Is there at least nThreshold pixels in the intersection of the depth map and - * this virtual object? - * - * @param [in] dmOther The input depth map. - * @param [in] nThreshold The minimal number of pixels to consider intersection. - */ - virtual XnBool IsIntersect(const XnVDepthMap& dmOther, XnUInt32 nThreshold) = 0; - /** - * What is the size of the intersection between the input depth map and this virtual object? - * - * @param [in] dmOther The input depth map. - */ - virtual XnUInt32 IntersectionSize(const XnVDepthMap& dmOther) = 0; - -protected: - /** - * Sets a Projective bounding box. - * This Projective bounding box will assist in intersections. - * - * @param [in] ptMins Minimum point - * @param [in] ptMaxs Maximum point - * @param [in] drDepth Depth representation, mainly for the Real World Translator inside. - * @param [in] bProjective If the input isn't Projective (false, which means Real World), the points should be translated. - */ - XnStatus SetBoundingBox(const XnVPoint& ptMins, const XnVPoint& ptMaxs, const XnVDepthRepresentation& drDepth, XnBool bProjective); - - XnUInt16 m_nXResWhenBounding, m_nYResWhenBounding; - XnVBoundingBox m_BoundingBox; -}; - - -#endif //_XNV_VIRTUAL_OBJECT_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XNV_VIRTUAL_OBJECT_H_ +#define _XNV_VIRTUAL_OBJECT_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnVObject.h" +#include "XnVDepthMap.h" +#include "XnVBoundingBox.h" +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** + * XnVVirtualObject is a base class for all user-created objects that are inserted + * into the scene. + * Each of these objects must be able to intersect with a XnVDepthMap. + * The intersection is in Real World coordinations. + * Currently implemented virtual objects include XnV3DBox and XnVSphere. + */ + +class XN_EE_FW_API XnVVirtualObject : public XnVObject +{ +public: + XnVVirtualObject(); + + virtual ~XnVVirtualObject() {} + + /** + * Intersect the virtual object with the depth map. + * Intersection is done in Real World coordinations. + * Adds the pixels from the input depth map that are inside or on the virtual object + * to the output depth map. + * No pixels are deleted from the output depth map if they already exist. + * + * @param [in] dmOther The input depth map on which to run. + * @param [in,out] dmOutput The output depth map, with only the pixels inside or on the virtual object. + */ + virtual XnUInt32 Intersect(const XnVDepthMap& dmOther, XnVDepthMap& dmOutput) = 0; + /** + * Is there at least nThreshold pixels in the intersection of the depth map and + * this virtual object? + * + * @param [in] dmOther The input depth map. + * @param [in] nThreshold The minimal number of pixels to consider intersection. + */ + virtual XnBool IsIntersect(const XnVDepthMap& dmOther, XnUInt32 nThreshold) = 0; + /** + * What is the size of the intersection between the input depth map and this virtual object? + * + * @param [in] dmOther The input depth map. + */ + virtual XnUInt32 IntersectionSize(const XnVDepthMap& dmOther) = 0; + +protected: + /** + * Sets a Projective bounding box. + * This Projective bounding box will assist in intersections. + * + * @param [in] ptMins Minimum point + * @param [in] ptMaxs Maximum point + * @param [in] drDepth Depth representation, mainly for the Real World Translator inside. + * @param [in] bProjective If the input isn't Projective (false, which means Real World), the points should be translated. + */ + XnStatus SetBoundingBox(const XnVPoint& ptMins, const XnVPoint& ptMaxs, const XnVDepthRepresentation& drDepth, XnBool bProjective); + + XnUInt16 m_nXResWhenBounding, m_nYResWhenBounding; + XnVBoundingBox m_BoundingBox; +}; + + +#endif //_XNV_VIRTUAL_OBJECT_H_ + diff --git a/Include/XnFormatsStatus.h b/Include/XnFormatsStatus.h index 0b81f07..27252b2 100644 --- a/Include/XnFormatsStatus.h +++ b/Include/XnFormatsStatus.h @@ -1,69 +1,69 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_FORMATS_STATUS_H_ -#define _XN_FORMATS_STATUS_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -XN_PS_STATUS_MESSAGE_MAP_START(XN_ERROR_GROUP_FORMATS) -XN_STATUS_MESSAGE(XN_STATUS_FORMATS_NOT_INIT, "Xiron Formats library was not initialized!") -XN_STATUS_MESSAGE(XN_STATUS_FORMATS_ALREADY_INIT, "Xiron Formats library was already initialized!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, "Invalid Xiron I/O stream depth format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, "Invalid Xiron I/O stream image format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT, "Invalid Xiron I/O stream misc format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT, "Invalid Xiron I/O stream audio format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSION_INIT_FAILED, "Xiron I/O compression initialization failed!") -XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSION_FAILED, "Xiron I/O compression failed!") -XN_STATUS_MESSAGE(XN_STATUS_IO_DECOMPRESSION_FAILED, "Xiron I/O decompression failed!") -XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL, "The compressed input buffer is too small to be valid!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_COMPRESSED_BUFFER_SIZE, "Invalid compressed buffer size!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT, "Invalid depth compression format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT, "Invalid image stream compression format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT, "Invalid misc stream compression format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT, "Invalid audio stream compression format!") -XN_STATUS_MESSAGE(XN_STATUS_IO_UNSUPPORTED_COMPRESSION_FORMAT, "This compression format is no longer supported!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_PACKED_BUFFER, "Invalid Xiron I/O packed stream buffer!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_HEADER, "Invalid Xiron I/O stream header!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_BUFFER, "Invalid Xiron I/O stream depth buffer!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_BUFFER, "Invalid Xiron I/O stream image buffer!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_BUFFER, "Invalid Xiron I/O stream misc buffer!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER, "Invalid Xiron I/O stream audio buffer!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_BUFFER_SIZE, "Invalid Xiron I/O stream depth buffer size!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_BUFFER_SIZE, "Invalid Xiron I/O stream image buffer size!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_BUFFER_SIZE, "Invalid Xiron I/O stream misc buffer size!") -XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER_SIZE, "Invalid Xiron I/O stream audio buffer size!") -XN_PS_STATUS_MESSAGE_MAP_END(XN_ERROR_GROUP_FORMATS) - -#endif //_XN_FORMATS_STATUS_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_FORMATS_STATUS_H_ +#define _XN_FORMATS_STATUS_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +XN_PS_STATUS_MESSAGE_MAP_START(XN_ERROR_GROUP_FORMATS) +XN_STATUS_MESSAGE(XN_STATUS_FORMATS_NOT_INIT, "Xiron Formats library was not initialized!") +XN_STATUS_MESSAGE(XN_STATUS_FORMATS_ALREADY_INIT, "Xiron Formats library was already initialized!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, "Invalid Xiron I/O stream depth format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, "Invalid Xiron I/O stream image format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT, "Invalid Xiron I/O stream misc format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT, "Invalid Xiron I/O stream audio format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSION_INIT_FAILED, "Xiron I/O compression initialization failed!") +XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSION_FAILED, "Xiron I/O compression failed!") +XN_STATUS_MESSAGE(XN_STATUS_IO_DECOMPRESSION_FAILED, "Xiron I/O decompression failed!") +XN_STATUS_MESSAGE(XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL, "The compressed input buffer is too small to be valid!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_COMPRESSED_BUFFER_SIZE, "Invalid compressed buffer size!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT, "Invalid depth compression format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT, "Invalid image stream compression format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT, "Invalid misc stream compression format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT, "Invalid audio stream compression format!") +XN_STATUS_MESSAGE(XN_STATUS_IO_UNSUPPORTED_COMPRESSION_FORMAT, "This compression format is no longer supported!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_PACKED_BUFFER, "Invalid Xiron I/O packed stream buffer!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_HEADER, "Invalid Xiron I/O stream header!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_BUFFER, "Invalid Xiron I/O stream depth buffer!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_BUFFER, "Invalid Xiron I/O stream image buffer!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_BUFFER, "Invalid Xiron I/O stream misc buffer!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER, "Invalid Xiron I/O stream audio buffer!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_DEPTH_BUFFER_SIZE, "Invalid Xiron I/O stream depth buffer size!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_IMAGE_BUFFER_SIZE, "Invalid Xiron I/O stream image buffer size!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_MISC_BUFFER_SIZE, "Invalid Xiron I/O stream misc buffer size!") +XN_STATUS_MESSAGE(XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER_SIZE, "Invalid Xiron I/O stream audio buffer size!") +XN_PS_STATUS_MESSAGE_MAP_END(XN_ERROR_GROUP_FORMATS) + +#endif //_XN_FORMATS_STATUS_H_ diff --git a/Include/XnIOFileStream.h b/Include/XnIOFileStream.h index a448f65..d354b2c 100644 --- a/Include/XnIOFileStream.h +++ b/Include/XnIOFileStream.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IO_FILE_STREAM_H__ -#define __XN_IO_FILE_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_CORE_CPP_API XnIOFileStream : public XnIOStream -{ -public: - XnIOFileStream(const XnChar* pcsFileName, XnUInt32 nFlags); - ~XnIOFileStream() { Free(); } - - virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize); - virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize); - virtual XnStatus Init(); - virtual XnStatus Free(); - - XnStatus Tell(XnUInt32* pnOffset); - XnStatus Seek(XnUInt32 nOffset); - -private: - const XnChar* m_pcsFileName; - XnUInt32 m_nFlags; - XN_FILE_HANDLE m_hFile; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IO_FILE_STREAM_H__ +#define __XN_IO_FILE_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_CORE_CPP_API XnIOFileStream : public XnIOStream +{ +public: + XnIOFileStream(const XnChar* pcsFileName, XnUInt32 nFlags); + ~XnIOFileStream() { Free(); } + + virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize); + virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize); + virtual XnStatus Init(); + virtual XnStatus Free(); + + XnStatus Tell(XnUInt32* pnOffset); + XnStatus Seek(XnUInt32 nOffset); + +private: + const XnChar* m_pcsFileName; + XnUInt32 m_nFlags; + XN_FILE_HANDLE m_hFile; +}; + #endif //__XN_IO_FILE_STREAM_H__ \ No newline at end of file diff --git a/Include/XnIONetworkStream.h b/Include/XnIONetworkStream.h index 4ba5b6f..61e980f 100644 --- a/Include/XnIONetworkStream.h +++ b/Include/XnIONetworkStream.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IO_NETWORK_STREAM_H__ -#define __XN_IO_NETWORK_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_CORE_CPP_API XnIONetworkStream : public XnIOStream -{ -public: - XnIONetworkStream(XN_SOCKET_HANDLE hSocket); - ~XnIONetworkStream() { Free(); } - - virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize); - virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize); - virtual XnStatus Init(); - virtual XnStatus Free(); - inline XnBool IsConnected() const { return m_bIsConnected; } - void SetReadTimeout(XnUInt32 nMicrosecondsReadTimeout); - -private: - XnUInt32 m_nReadTimeout; - XN_SOCKET_HANDLE m_hSocket; - XnBool m_bIsConnected; - -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IO_NETWORK_STREAM_H__ +#define __XN_IO_NETWORK_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_CORE_CPP_API XnIONetworkStream : public XnIOStream +{ +public: + XnIONetworkStream(XN_SOCKET_HANDLE hSocket); + ~XnIONetworkStream() { Free(); } + + virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize); + virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize); + virtual XnStatus Init(); + virtual XnStatus Free(); + inline XnBool IsConnected() const { return m_bIsConnected; } + void SetReadTimeout(XnUInt32 nMicrosecondsReadTimeout); + +private: + XnUInt32 m_nReadTimeout; + XN_SOCKET_HANDLE m_hSocket; + XnBool m_bIsConnected; + +}; + #endif //__XN_IO_NETWORK_STREAM_H__ \ No newline at end of file diff --git a/Include/XnIOParams.h b/Include/XnIOParams.h index bed373f..cc33372 100644 --- a/Include/XnIOParams.h +++ b/Include/XnIOParams.h @@ -1,193 +1,193 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_IO_PARAMS_H_ -#define _XN_IO_PARAMS_H_ - -#include -#include -#include - -#define XN_IO_PARAM_MIN_DEPTH_VALUE "MinDepthValue" -#define XN_IO_PARAM_MAX_DEPTH_VALUE "MaxDepthValue" -#define XN_IO_PARAM_FRAME_DELAY "FrameDelay" -#define XN_IO_PARAM_DEPTH_COMPRESSION "DepthCompression" -#define XN_IO_PARAM_IMAGE_COMPRESSION "ImageCompression" -#define XN_IO_PARAM_MISC_COMPRESSION "MiscCompression" -#define XN_IO_PARAM_AUDIO_COMPRESSION "AudioCompression" -#define XN_IO_PARAM_RGB_REGISTRAR_STATE "RGBRegistrarState" -#define XN_IO_PARAM_AUDIO_ENABLED "AudioEnabled" -#define XN_IO_PARAM_AUDIO_LEFT_CHANNEL_VOLUME "AudioLeftChannelVolume" -#define XN_IO_PARAM_AUDIO_RIGHT_CHANNEL_VOLUME "AudioRightChannelVolume" -#define XN_IO_PARAM_AUDIO_SAMPLE_RATE "AudioSampleRate" -#define XN_IO_PARAM_AUDIO_READ_MODE "AudioReadMode" -#define XN_IO_PARAM_AUDIO_READ_CHUNK_SIZE "AudioReadChunkSize" -#define XN_IO_PARAM_AUDIO_READ_SYNC "AudioReadSync" -#define XN_IO_PARAM_DEPTH_WHITE_BALANCE "DepthWhiteBalance" -#define XN_IO_PARAM_DEPTH_INPUT_FORMAT "DepthInputFormat" -#define XN_IO_PARAM_IMAGE_INPUT_FORMAT "ImageInputFormat" -#define XN_IO_PARAM_DEPTH_STATE "DepthState" -#define XN_IO_PARAM_IMAGE_STATE "ImageState" -#define XN_IO_PARAM_HIGHRES_TIMESTAMPS "HighresTimestamps" - - -#define XN_IO_REGMODE_NO_REGISTER (XnUInt32)0 -#define XN_IO_REGMODE_IMAGE_TO_DEPTH (XnUInt32)1 -#define XN_IO_REGMODE_DEPTH_TO_IMAGE (XnUInt32)2 - -#ifdef _XN_DEPRECATE_OLD_IO -#pragma deprecated ("XN_IO_PARAM_MIN_DEPTH_VALUE", "XN_IO_PARAM_MAX_DEPTH_VALUE", "XN_IO_PARAM_FRAME_DELAY", "XN_IO_PARAM_DEPTH_COMPRESSION") -#pragma deprecated ("XN_IO_PARAM_IMAGE_COMPRESSION", "XN_IO_PARAM_MISC_COMPRESSION", "XN_IO_PARAM_AUDIO_COMPRESSION", "XN_IO_PARAM_RGB_REGISTRAR_STATE") -#pragma deprecated ("XN_IO_PARAM_AUDIO_ENABLED", "XN_IO_PARAM_AUDIO_LEFT_CHANNEL_VOLUME", "XN_IO_PARAM_AUDIO_RIGHT_CHANNEL_VOLUME") -#pragma deprecated ("XN_IO_PARAM_AUDIO_SAMPLE_RATE", "XN_IO_PARAM_AUDIO_READ_MODE", "XN_IO_PARAM_AUDIO_READ_CHUNK_SIZE") -#pragma deprecated ("XN_IO_PARAM_AUDIO_READ_SYNC", "XN_IO_PARAM_GMC_MODE", "XN_IO_PARAM_DEPTH_WHITE_BALANCE", "XN_IO_PARAM_DEPTH_INPUT_FORMAT") -#pragma deprecated ("XN_IO_PARAM_IMAGE_INPUT_FORMAT", "XN_IO_PARAM_DEPTH_STATE", "XN_IO_PARAM_IMAGE_STATE", "XN_IO_PARAM_READ_LOG_INTERVAL") -#pragma deprecated ("XN_IO_REGMODE_NO_REGISTER", "XN_IO_REGMODE_IMAGE_TO_DEPTH", "XN_IO_REGMODE_DEPTH_TO_IMAGE") -#endif - -typedef XN_OLD_IO_API enum XnIOParams -{ - XN_IO_PARAM_IMAGE_RESOLUTION = 0, // Get only for now - XN_IO_PARAM_IMAGE_FPS = 1, // Get only for now - XN_IO_PARAM_IMAGE_AGC = 2, // PARAM_RGB_AGC - XN_IO_PARAM_IMAGE_CONTROL_PROCESSING = 3, // I2C - XN_IO_PARAM_IMAGE_FLICKER_DETECTION = 4, // PARAM_IMAGE_FLICKER_DETECTION - - XN_IO_PARAM_DEPTH_RESOLUTION = 5, // Get only for now - XN_IO_PARAM_DEPTH_FPS = 6, // Get only for now - XN_IO_PARAM_DEPTH_AGC = 7, // PARAM_DEPTH_AGC - XN_IO_PARAM_DEPTH_HOLE_FILTER = 8, // PARAM_HOLE_FILTER - XN_IO_PARAM_DEPTH_CONTROL_PROCESSING = 9, // I2C - - XN_IO_PARAM_IR_RESOLUTION = 10, // Get only for now - XN_IO_PARAM_IR_FPS = 11, // Get only for now - XN_IO_PARAM_IR_AGC = 12, - - XN_IO_PARAM_REGISTRATION = 13, // PARAM_REGISTRATION_ENABLE - XN_IO_PARAM_FRAME_SYNC = 14, // PARAM_FRAME_SYNC_BY - XN_IO_PARAM_DEPTH_MIRROR = 15, // PARAM_MIRROR - - XN_IO_PARAM_INNER_PARAM = 17, // PARAM - XN_IO_PARAM_VERSION = 18, // VERSION - XN_IO_PARAM_PRIMARY = 25, // 'Read' returns when new image, new depth or new any received - XN_IO_PARAM_READ_WRITE_MODE = 26, // Get only - - XN_IO_PARAM_SHIFT2DEPTH = 27, - XN_IO_PARAM_DEPTH2SHIFT = 28, - - XN_IO_PARAM_RESET = 29, // Reset (either power or software) - - XN_IO_PARAM_CURRENT_MODE = 31, // Maintenance/Normal - - XN_IO_PARAM_LAST_RAW_IMAGE = 32, // Last RAW Image - - XN_IO_PARAM_IR_CROPPING = 33, // IR Cropping - - XN_IO_PARAM_IMAGE_QUALITY = 38, // Image Quality - 0-default, 1-low, 2-medium, 3-high - XN_IO_PARAM_CMOS_BLANKING_UNITS = 46, // XnCmosBlanking - XN_IO_PARAM_CMOS_BLANKING_TIME = 47, // XnCmosBlankingTime - - XN_IO_PARAM_DEPTH_AGC_BIN = 48, // XnDepthAGCBin - - XN_IO_PARAM_SUPPORTS_MIRRORING = 49, // Is mirror supported (bool, get only) - XN_IO_PARAM_MIRROR = 50, - XN_IO_PARAM_IMAGE_MIRROR = 51, - XN_IO_PARAM_IR_MIRROR = 52, - -} XnIOParams; - -typedef XN_OLD_IO_API enum -{ - XN_IO_DEPTH_DECIMATION_DISABLED, - XN_IO_DEPTH_DECIMATION_ENABLED -} XnIODepthDecimation; - -// some structs here that are deprecated holds other deprecated, so disable warnings -#pragma warning (push) -#pragma warning (disable: XN_DEPRECATED_WARNING_IDS) - -typedef XN_OLD_IO_API struct XnDeviceSensorParameters -{ - XnBool bConfigure; - XnUInt8 VideoMode; - XnBool bAudioOn; - XnIOImageFormats ImageFormat; - XnIODepthFormats DepthFormat; - XnIODepthDecimation DepthDecimation; -} XnDeviceSensorParameters; - -typedef XN_OLD_IO_API enum -{ - XN_PRIMARY_ANY, - XN_PRIMARY_DEPTH, - XN_PRIMARY_IMAGE -} XnParamPrimary; - -#pragma pack (push, 1) - -typedef XN_OLD_IO_API struct { - XnUChar* pBuffer; - XnUInt32 nBufferSize; -} XnDataBuffer; - -#pragma pack (pop) - -#pragma warning (pop) - -// Set Param -// (xx)(yyy)(zzz) - byte comprised of mode(x), stream0(y), stream1(z) -#define XN_VIDEO_PS_MODE 0 -#define XN_VIDEO_WEBCAM_MODE 1 - -#define XN_VIDEO_CURRENT_GET_MODE(x) (((x)>>6)&0x03) -#define XN_VIDEO_STREAM0_GET_MODE(x) (((x)>>3)&0x07) -#define XN_VIDEO_STREAM1_GET_MODE(x) ((x)&0x07) -#define XN_VIDEO_CURRENT_MODE(x) ((x)<<6) -#define XN_VIDEO_STREAM0_MODE(x) (((x)&0x7)<<3) -#define XN_VIDEO_STREAM1_MODE(x) ((x)&0x7) -#define XN_VIDEO_MODE(current, stream0, stream1) \ - (XN_VIDEO_CURRENT_MODE(current)|XN_VIDEO_STREAM0_MODE(stream0)|XN_VIDEO_STREAM1_MODE(stream1)) - -#define XN_VIDEO_MODE_OFF XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_OFF, XN_VIDEO_STREAM_OFF) // 0x00 -#define XN_VIDEO_MODE_COLOR_PS XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_OFF) // 0x08 -#define XN_VIDEO_MODE_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_IR, XN_VIDEO_STREAM_OFF) // 0x18 -#define XN_VIDEO_MODE_DEPTH XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_OFF, XN_VIDEO_STREAM_DEPTH)// 0x02 -#define XN_VIDEO_MODE_COLOR_DEPTH XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_DEPTH)// 0x0a -#define XN_VIDEO_MODE_DEPTH_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_IR, XN_VIDEO_STREAM_DEPTH)// 0x1a -// Not supported for now? -#define XN_VIDEO_MODE_WEBCAM XN_VIDEO_MODE(XN_VIDEO_WEBCAM_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_OFF) // 0x48 -#define XN_VIDEO_MODE_COLOR_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_IR) // 0x0b - -#ifdef _XN_DEPRECATE_OLD_IO -#pragma deprecated ("XN_VIDEO_PS_MODE", "XN_VIDEO_WEBCAM_MODE") -#pragma deprecated ("XN_VIDEO_CURRENT_GET_MODE", "XN_VIDEO_STREAM0_GET_MODE", "XN_VIDEO_STREAM1_GET_MODE") -#pragma deprecated ("XN_VIDEO_CURRENT_MODE", "XN_VIDEO_STREAM0_MODE", "XN_VIDEO_STREAM1_MODE", "XN_VIDEO_MODE") -#pragma deprecated ("XN_VIDEO_MODE_OFF", "XN_VIDEO_MODE_COLOR_PS", "XN_VIDEO_MODE_IR", "XN_VIDEO_MODE_DEPTH") -#pragma deprecated ("XN_VIDEO_MODE_COLOR_DEPTH", "XN_VIDEO_MODE_DEPTH_IR", "XN_VIDEO_MODE_WEBCAM", "XN_VIDEO_MODE_COLOR_IR") -#endif - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_IO_PARAMS_H_ +#define _XN_IO_PARAMS_H_ + +#include +#include +#include + +#define XN_IO_PARAM_MIN_DEPTH_VALUE "MinDepthValue" +#define XN_IO_PARAM_MAX_DEPTH_VALUE "MaxDepthValue" +#define XN_IO_PARAM_FRAME_DELAY "FrameDelay" +#define XN_IO_PARAM_DEPTH_COMPRESSION "DepthCompression" +#define XN_IO_PARAM_IMAGE_COMPRESSION "ImageCompression" +#define XN_IO_PARAM_MISC_COMPRESSION "MiscCompression" +#define XN_IO_PARAM_AUDIO_COMPRESSION "AudioCompression" +#define XN_IO_PARAM_RGB_REGISTRAR_STATE "RGBRegistrarState" +#define XN_IO_PARAM_AUDIO_ENABLED "AudioEnabled" +#define XN_IO_PARAM_AUDIO_LEFT_CHANNEL_VOLUME "AudioLeftChannelVolume" +#define XN_IO_PARAM_AUDIO_RIGHT_CHANNEL_VOLUME "AudioRightChannelVolume" +#define XN_IO_PARAM_AUDIO_SAMPLE_RATE "AudioSampleRate" +#define XN_IO_PARAM_AUDIO_READ_MODE "AudioReadMode" +#define XN_IO_PARAM_AUDIO_READ_CHUNK_SIZE "AudioReadChunkSize" +#define XN_IO_PARAM_AUDIO_READ_SYNC "AudioReadSync" +#define XN_IO_PARAM_DEPTH_WHITE_BALANCE "DepthWhiteBalance" +#define XN_IO_PARAM_DEPTH_INPUT_FORMAT "DepthInputFormat" +#define XN_IO_PARAM_IMAGE_INPUT_FORMAT "ImageInputFormat" +#define XN_IO_PARAM_DEPTH_STATE "DepthState" +#define XN_IO_PARAM_IMAGE_STATE "ImageState" +#define XN_IO_PARAM_HIGHRES_TIMESTAMPS "HighresTimestamps" + + +#define XN_IO_REGMODE_NO_REGISTER (XnUInt32)0 +#define XN_IO_REGMODE_IMAGE_TO_DEPTH (XnUInt32)1 +#define XN_IO_REGMODE_DEPTH_TO_IMAGE (XnUInt32)2 + +#ifdef _XN_DEPRECATE_OLD_IO +#pragma deprecated ("XN_IO_PARAM_MIN_DEPTH_VALUE", "XN_IO_PARAM_MAX_DEPTH_VALUE", "XN_IO_PARAM_FRAME_DELAY", "XN_IO_PARAM_DEPTH_COMPRESSION") +#pragma deprecated ("XN_IO_PARAM_IMAGE_COMPRESSION", "XN_IO_PARAM_MISC_COMPRESSION", "XN_IO_PARAM_AUDIO_COMPRESSION", "XN_IO_PARAM_RGB_REGISTRAR_STATE") +#pragma deprecated ("XN_IO_PARAM_AUDIO_ENABLED", "XN_IO_PARAM_AUDIO_LEFT_CHANNEL_VOLUME", "XN_IO_PARAM_AUDIO_RIGHT_CHANNEL_VOLUME") +#pragma deprecated ("XN_IO_PARAM_AUDIO_SAMPLE_RATE", "XN_IO_PARAM_AUDIO_READ_MODE", "XN_IO_PARAM_AUDIO_READ_CHUNK_SIZE") +#pragma deprecated ("XN_IO_PARAM_AUDIO_READ_SYNC", "XN_IO_PARAM_GMC_MODE", "XN_IO_PARAM_DEPTH_WHITE_BALANCE", "XN_IO_PARAM_DEPTH_INPUT_FORMAT") +#pragma deprecated ("XN_IO_PARAM_IMAGE_INPUT_FORMAT", "XN_IO_PARAM_DEPTH_STATE", "XN_IO_PARAM_IMAGE_STATE", "XN_IO_PARAM_READ_LOG_INTERVAL") +#pragma deprecated ("XN_IO_REGMODE_NO_REGISTER", "XN_IO_REGMODE_IMAGE_TO_DEPTH", "XN_IO_REGMODE_DEPTH_TO_IMAGE") +#endif + +typedef XN_OLD_IO_API enum XnIOParams +{ + XN_IO_PARAM_IMAGE_RESOLUTION = 0, // Get only for now + XN_IO_PARAM_IMAGE_FPS = 1, // Get only for now + XN_IO_PARAM_IMAGE_AGC = 2, // PARAM_RGB_AGC + XN_IO_PARAM_IMAGE_CONTROL_PROCESSING = 3, // I2C + XN_IO_PARAM_IMAGE_FLICKER_DETECTION = 4, // PARAM_IMAGE_FLICKER_DETECTION + + XN_IO_PARAM_DEPTH_RESOLUTION = 5, // Get only for now + XN_IO_PARAM_DEPTH_FPS = 6, // Get only for now + XN_IO_PARAM_DEPTH_AGC = 7, // PARAM_DEPTH_AGC + XN_IO_PARAM_DEPTH_HOLE_FILTER = 8, // PARAM_HOLE_FILTER + XN_IO_PARAM_DEPTH_CONTROL_PROCESSING = 9, // I2C + + XN_IO_PARAM_IR_RESOLUTION = 10, // Get only for now + XN_IO_PARAM_IR_FPS = 11, // Get only for now + XN_IO_PARAM_IR_AGC = 12, + + XN_IO_PARAM_REGISTRATION = 13, // PARAM_REGISTRATION_ENABLE + XN_IO_PARAM_FRAME_SYNC = 14, // PARAM_FRAME_SYNC_BY + XN_IO_PARAM_DEPTH_MIRROR = 15, // PARAM_MIRROR + + XN_IO_PARAM_INNER_PARAM = 17, // PARAM + XN_IO_PARAM_VERSION = 18, // VERSION + XN_IO_PARAM_PRIMARY = 25, // 'Read' returns when new image, new depth or new any received + XN_IO_PARAM_READ_WRITE_MODE = 26, // Get only + + XN_IO_PARAM_SHIFT2DEPTH = 27, + XN_IO_PARAM_DEPTH2SHIFT = 28, + + XN_IO_PARAM_RESET = 29, // Reset (either power or software) + + XN_IO_PARAM_CURRENT_MODE = 31, // Maintenance/Normal + + XN_IO_PARAM_LAST_RAW_IMAGE = 32, // Last RAW Image + + XN_IO_PARAM_IR_CROPPING = 33, // IR Cropping + + XN_IO_PARAM_IMAGE_QUALITY = 38, // Image Quality - 0-default, 1-low, 2-medium, 3-high + XN_IO_PARAM_CMOS_BLANKING_UNITS = 46, // XnCmosBlanking + XN_IO_PARAM_CMOS_BLANKING_TIME = 47, // XnCmosBlankingTime + + XN_IO_PARAM_DEPTH_AGC_BIN = 48, // XnDepthAGCBin + + XN_IO_PARAM_SUPPORTS_MIRRORING = 49, // Is mirror supported (bool, get only) + XN_IO_PARAM_MIRROR = 50, + XN_IO_PARAM_IMAGE_MIRROR = 51, + XN_IO_PARAM_IR_MIRROR = 52, + +} XnIOParams; + +typedef XN_OLD_IO_API enum +{ + XN_IO_DEPTH_DECIMATION_DISABLED, + XN_IO_DEPTH_DECIMATION_ENABLED +} XnIODepthDecimation; + +// some structs here that are deprecated holds other deprecated, so disable warnings +#pragma warning (push) +#pragma warning (disable: XN_DEPRECATED_WARNING_IDS) + +typedef XN_OLD_IO_API struct XnDeviceSensorParameters +{ + XnBool bConfigure; + XnUInt8 VideoMode; + XnBool bAudioOn; + XnIOImageFormats ImageFormat; + XnIODepthFormats DepthFormat; + XnIODepthDecimation DepthDecimation; +} XnDeviceSensorParameters; + +typedef XN_OLD_IO_API enum +{ + XN_PRIMARY_ANY, + XN_PRIMARY_DEPTH, + XN_PRIMARY_IMAGE +} XnParamPrimary; + +#pragma pack (push, 1) + +typedef XN_OLD_IO_API struct { + XnUChar* pBuffer; + XnUInt32 nBufferSize; +} XnDataBuffer; + +#pragma pack (pop) + +#pragma warning (pop) + +// Set Param +// (xx)(yyy)(zzz) - byte comprised of mode(x), stream0(y), stream1(z) +#define XN_VIDEO_PS_MODE 0 +#define XN_VIDEO_WEBCAM_MODE 1 + +#define XN_VIDEO_CURRENT_GET_MODE(x) (((x)>>6)&0x03) +#define XN_VIDEO_STREAM0_GET_MODE(x) (((x)>>3)&0x07) +#define XN_VIDEO_STREAM1_GET_MODE(x) ((x)&0x07) +#define XN_VIDEO_CURRENT_MODE(x) ((x)<<6) +#define XN_VIDEO_STREAM0_MODE(x) (((x)&0x7)<<3) +#define XN_VIDEO_STREAM1_MODE(x) ((x)&0x7) +#define XN_VIDEO_MODE(current, stream0, stream1) \ + (XN_VIDEO_CURRENT_MODE(current)|XN_VIDEO_STREAM0_MODE(stream0)|XN_VIDEO_STREAM1_MODE(stream1)) + +#define XN_VIDEO_MODE_OFF XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_OFF, XN_VIDEO_STREAM_OFF) // 0x00 +#define XN_VIDEO_MODE_COLOR_PS XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_OFF) // 0x08 +#define XN_VIDEO_MODE_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_IR, XN_VIDEO_STREAM_OFF) // 0x18 +#define XN_VIDEO_MODE_DEPTH XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_OFF, XN_VIDEO_STREAM_DEPTH)// 0x02 +#define XN_VIDEO_MODE_COLOR_DEPTH XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_DEPTH)// 0x0a +#define XN_VIDEO_MODE_DEPTH_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_IR, XN_VIDEO_STREAM_DEPTH)// 0x1a +// Not supported for now? +#define XN_VIDEO_MODE_WEBCAM XN_VIDEO_MODE(XN_VIDEO_WEBCAM_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_OFF) // 0x48 +#define XN_VIDEO_MODE_COLOR_IR XN_VIDEO_MODE(XN_VIDEO_PS_MODE, XN_VIDEO_STREAM_COLOR, XN_VIDEO_STREAM_IR) // 0x0b + +#ifdef _XN_DEPRECATE_OLD_IO +#pragma deprecated ("XN_VIDEO_PS_MODE", "XN_VIDEO_WEBCAM_MODE") +#pragma deprecated ("XN_VIDEO_CURRENT_GET_MODE", "XN_VIDEO_STREAM0_GET_MODE", "XN_VIDEO_STREAM1_GET_MODE") +#pragma deprecated ("XN_VIDEO_CURRENT_MODE", "XN_VIDEO_STREAM0_MODE", "XN_VIDEO_STREAM1_MODE", "XN_VIDEO_MODE") +#pragma deprecated ("XN_VIDEO_MODE_OFF", "XN_VIDEO_MODE_COLOR_PS", "XN_VIDEO_MODE_IR", "XN_VIDEO_MODE_DEPTH") +#pragma deprecated ("XN_VIDEO_MODE_COLOR_DEPTH", "XN_VIDEO_MODE_DEPTH_IR", "XN_VIDEO_MODE_WEBCAM", "XN_VIDEO_MODE_COLOR_IR") +#endif + +#endif diff --git a/Include/XnIOStream.h b/Include/XnIOStream.h index 7d1f83c..6b1d7a2 100644 --- a/Include/XnIOStream.h +++ b/Include/XnIOStream.h @@ -1,52 +1,52 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IO_STREAM_H__ -#define __XN_IO_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_CORE_CPP_API XnIOStream -{ -public: - XnIOStream() {} - virtual ~XnIOStream() {} - - virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize) = 0; - virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize) = 0; - virtual XnStatus Init() { return XN_STATUS_OK; } - virtual XnStatus Free() { return XN_STATUS_OK; } -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IO_STREAM_H__ +#define __XN_IO_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_CORE_CPP_API XnIOStream +{ +public: + XnIOStream() {} + virtual ~XnIOStream() {} + + virtual XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize) = 0; + virtual XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize) = 0; + virtual XnStatus Init() { return XN_STATUS_OK; } + virtual XnStatus Free() { return XN_STATUS_OK; } +}; + #endif //__XN_IO_STREAM_H__ \ No newline at end of file diff --git a/Include/XnPlatformBC.h b/Include/XnPlatformBC.h index ac47afb..85f6d35 100644 --- a/Include/XnPlatformBC.h +++ b/Include/XnPlatformBC.h @@ -1,62 +1,62 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_PS_PLATFORM_H__ -#define __XN_PS_PLATFORM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -#define _XN_DEPRECATED_TYPE(newType, oldType) \ - XN_API_DEPRECATED("Please use " XN_STRINGIFY(newType) " instead.") typedef newType oldType; - -_XN_DEPRECATED_TYPE(XnChar, XN_CHAR) -_XN_DEPRECATED_TYPE(XnUChar, XN_UCHAR) -_XN_DEPRECATED_TYPE(XnInt8, XN_INT8) -_XN_DEPRECATED_TYPE(XnUInt8, XN_UINT8) -_XN_DEPRECATED_TYPE(XnInt16, XN_INT16) -_XN_DEPRECATED_TYPE(XnUInt16, XN_UINT16) -_XN_DEPRECATED_TYPE(XnInt32, XN_INT32) -_XN_DEPRECATED_TYPE(XnUInt32, XN_UINT32) -_XN_DEPRECATED_TYPE(XnInt64, XN_INT64) -_XN_DEPRECATED_TYPE(XnUInt64, XN_UINT64) -_XN_DEPRECATED_TYPE(XnFloat, XN_FLOAT) -_XN_DEPRECATED_TYPE(XnDouble, XN_DOUBLE) -_XN_DEPRECATED_TYPE(XnBool, XN_BOOL) -_XN_DEPRECATED_TYPE(XnWChar, XN_WCHAR) -_XN_DEPRECATED_TYPE(XnInt, XN_LONG) -_XN_DEPRECATED_TYPE(XnUInt, XN_ULONG) - -XN_API_DEPRECATED("Please use XnDepthPixel instead") typedef XnUInt16 XN_DEPTH_TYPE; -XN_API_DEPRECATED("Please use XnRGB24Pixel instead") typedef XnUChar XN_IMAGE_TYPE; - -#endif // __XN_PS_PLATFORM_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_PS_PLATFORM_H__ +#define __XN_PS_PLATFORM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +#define _XN_DEPRECATED_TYPE(newType, oldType) \ + XN_API_DEPRECATED("Please use " XN_STRINGIFY(newType) " instead.") typedef newType oldType; + +_XN_DEPRECATED_TYPE(XnChar, XN_CHAR) +_XN_DEPRECATED_TYPE(XnUChar, XN_UCHAR) +_XN_DEPRECATED_TYPE(XnInt8, XN_INT8) +_XN_DEPRECATED_TYPE(XnUInt8, XN_UINT8) +_XN_DEPRECATED_TYPE(XnInt16, XN_INT16) +_XN_DEPRECATED_TYPE(XnUInt16, XN_UINT16) +_XN_DEPRECATED_TYPE(XnInt32, XN_INT32) +_XN_DEPRECATED_TYPE(XnUInt32, XN_UINT32) +_XN_DEPRECATED_TYPE(XnInt64, XN_INT64) +_XN_DEPRECATED_TYPE(XnUInt64, XN_UINT64) +_XN_DEPRECATED_TYPE(XnFloat, XN_FLOAT) +_XN_DEPRECATED_TYPE(XnDouble, XN_DOUBLE) +_XN_DEPRECATED_TYPE(XnBool, XN_BOOL) +_XN_DEPRECATED_TYPE(XnWChar, XN_WCHAR) +_XN_DEPRECATED_TYPE(XnInt, XN_LONG) +_XN_DEPRECATED_TYPE(XnUInt, XN_ULONG) + +XN_API_DEPRECATED("Please use XnDepthPixel instead") typedef XnUInt16 XN_DEPTH_TYPE; +XN_API_DEPRECATED("Please use XnRGB24Pixel instead") typedef XnUChar XN_IMAGE_TYPE; + +#endif // __XN_PS_PLATFORM_H__ diff --git a/Include/XnPropertySet.h b/Include/XnPropertySet.h index 3e783cd..ddfcbcd 100644 --- a/Include/XnPropertySet.h +++ b/Include/XnPropertySet.h @@ -1,256 +1,256 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PROPERTY_SET_H__ -#define __XN_PROPERTY_SET_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -/** The type of the property. */ -typedef enum XnPropertyType -{ - XN_PROPERTY_TYPE_INTEGER, - XN_PROPERTY_TYPE_REAL, - XN_PROPERTY_TYPE_STRING, - XN_PROPERTY_TYPE_GENERAL, -} XnPropertyType; - -struct XnPropertySet; // Forward Declaration -typedef struct XnPropertySet XnPropertySet; - -struct XnPropertySetModuleEnumerator; // Forward Declaration -typedef struct XnPropertySetModuleEnumerator XnPropertySetModuleEnumerator; - -struct XnPropertySetEnumerator; // Forward Declaration -typedef struct XnPropertySetEnumerator XnPropertySetEnumerator; - -//--------------------------------------------------------------------------- -// Exported functions -//--------------------------------------------------------------------------- - -/** -* Creates a new property set. -* -* @param ppSet [out] A pointer to the new set. -*/ -XN_DDK_API XnStatus XnPropertySetCreate(XnPropertySet** ppSet); - -/** -* Destroys a previously created property set. -* -* @param ppSet [in/out] A pointer to the set. -*/ -XN_DDK_API XnStatus XnPropertySetDestroy(XnPropertySet** ppSet); - -/** -* Clears a property set from all the properties. -* -* @param pSet [in] The property set. -*/ -XN_DDK_API XnStatus XnPropertySetClear(XnPropertySet* pSet); - -/** -* Adds a module to the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module to add. -*/ -XN_DDK_API XnStatus XnPropertySetAddModule(XnPropertySet* pSet, const XnChar* strModuleName); - -/** -* Removes a module from the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module to remove. -*/ -XN_DDK_API XnStatus XnPropertySetRemoveModule(XnPropertySet* pSet, const XnChar* strModuleName); - -/** -* Adds an integer property to the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module. -* @param strModuleName [in] Name of the property to add. -* @param nValue [in] Value for that property. -*/ -XN_DDK_API XnStatus XnPropertySetAddIntProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnUInt64 nValue); - -/** -* Adds an real property to the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module. -* @param strModuleName [in] Name of the property to add. -* @param dValue [in] Value for that property. -*/ -XN_DDK_API XnStatus XnPropertySetAddRealProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnDouble dValue); - -/** -* Adds an string property to the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module. -* @param strModuleName [in] Name of the property to add. -* @param strValue [in] Value for that property. -*/ -XN_DDK_API XnStatus XnPropertySetAddStringProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnChar* strValue); - -/** -* Adds an general property to the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module. -* @param strModuleName [in] Name of the property to add. -* @param pgbValue [in] Value for that property. -*/ -XN_DDK_API XnStatus XnPropertySetAddGeneralProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnGeneralBuffer* pgbValue); - -/** -* Removes a property from the property set. -* -* @param pSet [in] The property set. -* @param strModuleName [in] Name of the module. -* @param strModuleName [in] Name of the property to remove. -*/ -XN_DDK_API XnStatus XnPropertySetRemoveProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty); - -/** -* Gets a modules enumerator. This enumerator should be freed using XnPropertySetModuleEnumeratorFree. -* -* @param pSet [in] The property set. -* @param ppEnumerator [out] The created enumerator. -*/ -XN_DDK_API XnStatus XnPropertySetGetModuleEnumerator(const XnPropertySet* pSet, XnPropertySetModuleEnumerator** ppEnumerator); - -/** -* Frees a previously created module enumerator. -* -* @param ppEnumerator [in/out] The enumerator. -*/ -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorFree(XnPropertySetModuleEnumerator** ppEnumer); - -/** -* Moves the enumerator to the next module. This function must be called *before* getting current. -* -* @param pEnumerator [in] The enumerator. -* @param pbEnd [out] TRUE if the enumerator has reached the end of the collection. -*/ -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorMoveNext(XnPropertySetModuleEnumerator* pEnumerator, XnBool* pbEnd); - -/** -* Gets the current module name from the enumerator. -* -* @param pEnumerator [in] The enumerator. -* @param pstrModuleName [out] The name of the current module. -*/ -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorGetCurrent(const XnPropertySetModuleEnumerator* pEnumer, const XnChar** pstrModuleName); - -/** -* Gets a property enumerator. This enumerator must be freed using XnPropertySetEnumeratorFree. -* -* @param pSet [in] The property set. -* @param ppEnumerator [in/out] The enumerator. -* @param strModule [in] Optional. When provided, only properties of this module will be enumerated. -*/ -XN_DDK_API XnStatus XnPropertySetGetEnumerator(const XnPropertySet* pSet, XnPropertySetEnumerator** ppEnumerator, const XnChar* strModule = NULL); - -/** -* Finds a property according to its name and module, and returns an enumerator to it. -* This enumerator must be freed using XnPropertySetEnumeratorFree. -* -* @param pSet [in] The property set. -* @param strModule [in] The module name. -* @param strProp [in] The property name. -* @param ppEnumerator [in/out] The enumerator. -*/ -XN_DDK_API XnStatus XnPropertySetFindProperty(const XnPropertySet* pSet, const XnChar* strModule, const XnChar* strProp, XnPropertySetEnumerator** ppEnumerator); - -/** -* Frees a previously created properties enumerator. -* -* @param ppEnumerator [in/out] The enumerator. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorFree(XnPropertySetEnumerator** ppEnumerator); - -/** -* Moves the enumerator to the next property. This function must be called *before* getting current. -* -* @param pEnumerator [in] The enumerator. -* @param pbEnd [out] TRUE if the enumerator has reached the end of the collection. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorMoveNext(XnPropertySetEnumerator* pEnumerator, XnBool* pbEnd); - -/** -* Gets information regarding the current property. -* -* @param pEnumerator [in] The enumerator. -* @param pnType [out] The type of the current property. -* @param pstrModule [out] The module of the current property. -* @param pstrProp [out] The name of the current property. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorGetCurrentPropertyInfo(const XnPropertySetEnumerator* pEnumerator, XnPropertyType* pnType, const XnChar** pstrModule, const XnChar** pstrProp); - -/** -* Gets the current integer value. -* -* @param pEnumerator [in] The enumerator. -* @param pnValue [out] The value of the property. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorGetIntValue(const XnPropertySetEnumerator* pEnumerator, XnUInt64* pnValue); - -/** -* Gets the current real property. -* -* @param pEnumerator [in] The enumerator. -* @param pdValue [out] The value of the property. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorGetRealValue(const XnPropertySetEnumerator* pEnumerator, XnDouble* pdValue); - -/** -* Gets the current string property. -* -* @param pEnumerator [in] The enumerator. -* @param pstrValue [out] The value of the property. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorGetStringValue(const XnPropertySetEnumerator* pEnumerator, const XnChar** pstrValue); - -/** -* Gets the current general property. -* -* @param pEnumerator [in] The enumerator. -* @param pgbValue [out] The value of the property. -*/ -XN_DDK_API XnStatus XnPropertySetEnumeratorGetGeneralValue(const XnPropertySetEnumerator* pEnumerator, XnGeneralBuffer* pgbValue); - -#endif //__XN_PROPERTY_SET_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PROPERTY_SET_H__ +#define __XN_PROPERTY_SET_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +/** The type of the property. */ +typedef enum XnPropertyType +{ + XN_PROPERTY_TYPE_INTEGER, + XN_PROPERTY_TYPE_REAL, + XN_PROPERTY_TYPE_STRING, + XN_PROPERTY_TYPE_GENERAL, +} XnPropertyType; + +struct XnPropertySet; // Forward Declaration +typedef struct XnPropertySet XnPropertySet; + +struct XnPropertySetModuleEnumerator; // Forward Declaration +typedef struct XnPropertySetModuleEnumerator XnPropertySetModuleEnumerator; + +struct XnPropertySetEnumerator; // Forward Declaration +typedef struct XnPropertySetEnumerator XnPropertySetEnumerator; + +//--------------------------------------------------------------------------- +// Exported functions +//--------------------------------------------------------------------------- + +/** +* Creates a new property set. +* +* @param ppSet [out] A pointer to the new set. +*/ +XN_DDK_API XnStatus XnPropertySetCreate(XnPropertySet** ppSet); + +/** +* Destroys a previously created property set. +* +* @param ppSet [in/out] A pointer to the set. +*/ +XN_DDK_API XnStatus XnPropertySetDestroy(XnPropertySet** ppSet); + +/** +* Clears a property set from all the properties. +* +* @param pSet [in] The property set. +*/ +XN_DDK_API XnStatus XnPropertySetClear(XnPropertySet* pSet); + +/** +* Adds a module to the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module to add. +*/ +XN_DDK_API XnStatus XnPropertySetAddModule(XnPropertySet* pSet, const XnChar* strModuleName); + +/** +* Removes a module from the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module to remove. +*/ +XN_DDK_API XnStatus XnPropertySetRemoveModule(XnPropertySet* pSet, const XnChar* strModuleName); + +/** +* Adds an integer property to the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module. +* @param strModuleName [in] Name of the property to add. +* @param nValue [in] Value for that property. +*/ +XN_DDK_API XnStatus XnPropertySetAddIntProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnUInt64 nValue); + +/** +* Adds an real property to the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module. +* @param strModuleName [in] Name of the property to add. +* @param dValue [in] Value for that property. +*/ +XN_DDK_API XnStatus XnPropertySetAddRealProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnDouble dValue); + +/** +* Adds an string property to the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module. +* @param strModuleName [in] Name of the property to add. +* @param strValue [in] Value for that property. +*/ +XN_DDK_API XnStatus XnPropertySetAddStringProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnChar* strValue); + +/** +* Adds an general property to the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module. +* @param strModuleName [in] Name of the property to add. +* @param pgbValue [in] Value for that property. +*/ +XN_DDK_API XnStatus XnPropertySetAddGeneralProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnGeneralBuffer* pgbValue); + +/** +* Removes a property from the property set. +* +* @param pSet [in] The property set. +* @param strModuleName [in] Name of the module. +* @param strModuleName [in] Name of the property to remove. +*/ +XN_DDK_API XnStatus XnPropertySetRemoveProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty); + +/** +* Gets a modules enumerator. This enumerator should be freed using XnPropertySetModuleEnumeratorFree. +* +* @param pSet [in] The property set. +* @param ppEnumerator [out] The created enumerator. +*/ +XN_DDK_API XnStatus XnPropertySetGetModuleEnumerator(const XnPropertySet* pSet, XnPropertySetModuleEnumerator** ppEnumerator); + +/** +* Frees a previously created module enumerator. +* +* @param ppEnumerator [in/out] The enumerator. +*/ +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorFree(XnPropertySetModuleEnumerator** ppEnumer); + +/** +* Moves the enumerator to the next module. This function must be called *before* getting current. +* +* @param pEnumerator [in] The enumerator. +* @param pbEnd [out] TRUE if the enumerator has reached the end of the collection. +*/ +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorMoveNext(XnPropertySetModuleEnumerator* pEnumerator, XnBool* pbEnd); + +/** +* Gets the current module name from the enumerator. +* +* @param pEnumerator [in] The enumerator. +* @param pstrModuleName [out] The name of the current module. +*/ +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorGetCurrent(const XnPropertySetModuleEnumerator* pEnumer, const XnChar** pstrModuleName); + +/** +* Gets a property enumerator. This enumerator must be freed using XnPropertySetEnumeratorFree. +* +* @param pSet [in] The property set. +* @param ppEnumerator [in/out] The enumerator. +* @param strModule [in] Optional. When provided, only properties of this module will be enumerated. +*/ +XN_DDK_API XnStatus XnPropertySetGetEnumerator(const XnPropertySet* pSet, XnPropertySetEnumerator** ppEnumerator, const XnChar* strModule = NULL); + +/** +* Finds a property according to its name and module, and returns an enumerator to it. +* This enumerator must be freed using XnPropertySetEnumeratorFree. +* +* @param pSet [in] The property set. +* @param strModule [in] The module name. +* @param strProp [in] The property name. +* @param ppEnumerator [in/out] The enumerator. +*/ +XN_DDK_API XnStatus XnPropertySetFindProperty(const XnPropertySet* pSet, const XnChar* strModule, const XnChar* strProp, XnPropertySetEnumerator** ppEnumerator); + +/** +* Frees a previously created properties enumerator. +* +* @param ppEnumerator [in/out] The enumerator. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorFree(XnPropertySetEnumerator** ppEnumerator); + +/** +* Moves the enumerator to the next property. This function must be called *before* getting current. +* +* @param pEnumerator [in] The enumerator. +* @param pbEnd [out] TRUE if the enumerator has reached the end of the collection. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorMoveNext(XnPropertySetEnumerator* pEnumerator, XnBool* pbEnd); + +/** +* Gets information regarding the current property. +* +* @param pEnumerator [in] The enumerator. +* @param pnType [out] The type of the current property. +* @param pstrModule [out] The module of the current property. +* @param pstrProp [out] The name of the current property. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorGetCurrentPropertyInfo(const XnPropertySetEnumerator* pEnumerator, XnPropertyType* pnType, const XnChar** pstrModule, const XnChar** pstrProp); + +/** +* Gets the current integer value. +* +* @param pEnumerator [in] The enumerator. +* @param pnValue [out] The value of the property. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorGetIntValue(const XnPropertySetEnumerator* pEnumerator, XnUInt64* pnValue); + +/** +* Gets the current real property. +* +* @param pEnumerator [in] The enumerator. +* @param pdValue [out] The value of the property. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorGetRealValue(const XnPropertySetEnumerator* pEnumerator, XnDouble* pdValue); + +/** +* Gets the current string property. +* +* @param pEnumerator [in] The enumerator. +* @param pstrValue [out] The value of the property. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorGetStringValue(const XnPropertySetEnumerator* pEnumerator, const XnChar** pstrValue); + +/** +* Gets the current general property. +* +* @param pEnumerator [in] The enumerator. +* @param pgbValue [out] The value of the property. +*/ +XN_DDK_API XnStatus XnPropertySetEnumeratorGetGeneralValue(const XnPropertySetEnumerator* pEnumerator, XnGeneralBuffer* pgbValue); + +#endif //__XN_PROPERTY_SET_H__ diff --git a/Include/XnPsVersion.h b/Include/XnPsVersion.h index f2c5461..8d3ab80 100644 --- a/Include/XnPsVersion.h +++ b/Include/XnPsVersion.h @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_PS_VERSION_H_ -#define _XN_PS_VERSION_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -/** Xiron major version. */ -#define XN_PS_MAJOR_VERSION 5 -/** Xiron minor version. */ -#define XN_PS_MINOR_VERSION 0 -/** Xiron maintenance version. */ -#define XN_PS_MAINTENANCE_VERSION 0 -/** Xiron build version. */ -#define XN_PS_BUILD_VERSION 24 - -/** Xiron version (in brief string format): "Major.Minor.Maintenance (Build)" */ -#define XN_PS_BRIEF_VERSION_STRING \ - XN_STRINGIFY(XN_PS_MAJOR_VERSION) "." \ - XN_STRINGIFY(XN_PS_MINOR_VERSION) "." \ - XN_STRINGIFY(XN_PS_MAINTENANCE_VERSION) \ - " (Build " XN_STRINGIFY(XN_PS_BUILD_VERSION) ")" - -/** Xiron version (in numeric format): (Xiron major version * 100000000 + Xiron minor version * 1000000 + Xiron maintenance version * 10000 + Xiron build version). */ -#define XN_PS_VERSION (XN_PS_MAJOR_VERSION*100000000 + XN_PS_MINOR_VERSION*1000000 + XN_PS_MAINTENANCE_VERSION*10000 + XN_PS_BUILD_VERSION) - -/** Xiron version (in string format): "Major.Minor.Maintenance.Build-Platform (MMM DD YYYY HH:MM:SS)". */ -#define XN_PS_VERSION_STRING \ - XN_PS_BRIEF_VERSION_STRING "-" \ - XN_PLATFORM_STRING " (" XN_TIMESTAMP ")" - -#endif //_XN_VERSION_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_PS_VERSION_H_ +#define _XN_PS_VERSION_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +/** Xiron major version. */ +#define XN_PS_MAJOR_VERSION 5 +/** Xiron minor version. */ +#define XN_PS_MINOR_VERSION 0 +/** Xiron maintenance version. */ +#define XN_PS_MAINTENANCE_VERSION 0 +/** Xiron build version. */ +#define XN_PS_BUILD_VERSION 25 + +/** Xiron version (in brief string format): "Major.Minor.Maintenance (Build)" */ +#define XN_PS_BRIEF_VERSION_STRING \ + XN_STRINGIFY(XN_PS_MAJOR_VERSION) "." \ + XN_STRINGIFY(XN_PS_MINOR_VERSION) "." \ + XN_STRINGIFY(XN_PS_MAINTENANCE_VERSION) \ + " (Build " XN_STRINGIFY(XN_PS_BUILD_VERSION) ")" + +/** Xiron version (in numeric format): (Xiron major version * 100000000 + Xiron minor version * 1000000 + Xiron maintenance version * 10000 + Xiron build version). */ +#define XN_PS_VERSION (XN_PS_MAJOR_VERSION*100000000 + XN_PS_MINOR_VERSION*1000000 + XN_PS_MAINTENANCE_VERSION*10000 + XN_PS_BUILD_VERSION) + +/** Xiron version (in string format): "Major.Minor.Maintenance.Build-Platform (MMM DD YYYY HH:MM:SS)". */ +#define XN_PS_VERSION_STRING \ + XN_PS_BRIEF_VERSION_STRING "-" \ + XN_PLATFORM_STRING " (" XN_TIMESTAMP ")" + +#endif //_XN_VERSION_H_ + diff --git a/Include/XnStream.h b/Include/XnStream.h index 5642246..ed3f3f1 100644 --- a/Include/XnStream.h +++ b/Include/XnStream.h @@ -1,351 +1,351 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - -#ifndef _XN_STREAM_H_ -#define _XN_STREAM_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -#if (!defined _XN_IO_BC && !defined XN_USE_DEVICE_3_6) - #define XN_OLD_IO_API XN_API_DEPRECATED("This is old XnIO API. Please use XnVDevice instead.") - #define _XN_DEPRECATE_OLD_IO -#else - #define XN_OLD_IO_API -#endif - -// some structs here that are deprecated holds other deprecated, so diable warnings -#pragma warning (push) -#pragma warning (disable: XN_DEPRECATED_WARNING_IDS) - -/** The stream flag unit. */ -#define XN_STREAM_FLAGS_TYPE XnInt32 - -/** Perform a horizontal flip on the output buffers. */ -#define XN_STREAM_FLAG_MIRROR 1 - -#ifdef _XN_DEPRECATE_OLD_IO -#pragma deprecated ("XN_STREAM_FLAGS_TYPE", "XN_STREAM_FLAG_MIRROR") -#endif - -typedef XN_OLD_IO_API enum XnAudioReadMode -{ - XN_AUDIO_READ_FRAMES, - XN_AUDIO_READ_STREAM -} XnAudioReadMode; - -//--------------------------------------------------------------------------- -// Stream Buffer Formats -//--------------------------------------------------------------------------- -/** The different types of depth buffers. */ -typedef XN_OLD_IO_API enum { - /** Disable the depth buffer. */ - XN_DEPTH_FORMAT_DISABLED = 0, - /** 10-bit depth values stored in a 16-bit buffer. */ - XN_DEPTH_FORMAT_RAW10 = 1, - /** 12-bit depth values stored in a 16-bit buffer. */ - XN_DEPTH_FORMAT_RAW12 = 2, - /** Shift values, in pixels. */ - XN_DEPTH_FORMAT_SHIFTS = 3, -} XnStreamDepthFormat; - -/** The different types of image buffers. */ -typedef XN_OLD_IO_API enum { - /** Disable the image buffer. */ - XN_IMAGE_FORMAT_DISABLED = 0, - /** Grayscale only image buffer. */ - XN_IMAGE_FORMAT_GRAYSCALE8 = 1, - /** Red, Green and Blue image buffer. */ - XN_IMAGE_FORMAT_RGB24 = 2, - /** YUV422 (uyvy) image buffer. */ - XN_IMAGE_FORMAT_YUV422 = 3, -} XnStreamImageFormat; - -/** The different types of audio buffers. */ -typedef XN_OLD_IO_API enum XnStreamAudioFormat { - /** Disable the audio buffer. */ - XN_AUDIO_FORMAT_DISABLED = 0, - /** PCM audio buffer. */ - XN_AUDIO_FORMAT_PCM, -} XnStreamAudioFormat; - -/** The different types of miscellaneous buffers. */ -typedef XN_OLD_IO_API enum { - /** Disable the miscellaneous buffer. */ - XN_MISC_FORMAT_DISABLED = 0, - /** 4-bit confidence map stored in an 8-bit buffer. */ - XN_MISC_FORMAT_CONFIDENCE_MAP = 1 -} XnStreamMiscFormat; - -/** The default depth buffer format. */ -#define XN_STREAM_DEFAULT_DEPTH_FORMAT XN_DEPTH_FORMAT_RAW12 -/** The default image buffer format. */ -#define XN_STREAM_DEFAULT_IMAGE_FORMAT XN_IMAGE_FORMAT_RGB24 -/** The default miscellaneous buffer format. */ -#define XN_STREAM_DEFAULT_MISC_FORMAT XN_MISC_FORMAT_CONFIDENCE_MAP - -#ifdef _XN_DEPRECATE_OLD_IO -#pragma deprecated (XN_STREAM_DEFAULT_DEPTH_FORMAT, XN_STREAM_DEFAULT_IMAGE_FORMAT, XN_STREAM_DEFAULT_MISC_FORMAT) -#endif - -//--------------------------------------------------------------------------- -// Stream Compressions -//--------------------------------------------------------------------------- - -/** The different types of depth stream compression formats. */ -typedef XN_OLD_IO_API enum { - /** Disable the depth buffer. */ - XN_COMPRESSED_DEPTH_FORMAT_SKIP = 0, - /** Uncompressed. */ - XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED = 1, - /** 16-bit Prime Sense Lossless Depth Compression. */ - XN_COMPRESSED_DEPTH_FORMAT_16Z = 2, - /** 16-bit Prime Sense Lossless Depth Compression + embedded tables. */ - XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE = 4, -} XnStreamDepthCompressionFormat; - -/** The different types of image stream compression formats. */ -typedef XN_OLD_IO_API enum { - /** Disable the image buffer. */ - XN_COMPRESSED_IMAGE_FORMAT_SKIP = 0, - /** Uncompressed. */ - XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED = 1, - /** 8-bit Prime Sense Lossless Image Compression. */ - XN_COMPRESSED_IMAGE_FORMAT_8Z = 2, - /** JPEG compression (default) */ - XN_COMPRESSED_IMAGE_FORMAT_JPEG = 3, - /** IR packed 10 bit */ - XN_COMPRESSED_IMAGE_FORMAT_IR10 = 4, -} XnStreamImageCompressionFormat; - -/** The different types of miscellaneous stream compression formats. */ -typedef XN_OLD_IO_API enum { - /** Disable the miscellaneous buffer. */ - XN_COMPRESSED_MISC_FORMAT_SKIP = 0, - /** Uncompressed. */ - XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED = 1, - /** 4-bit Confidence map. */ - XN_COMPRESSED_MISC_FORMAT_CONF4 = 2, - /** 4-bit Confidence map + simple LZ compression (UNSUPPORTED!). */ - XN_COMPRESSED_MISC_FORMAT_CONF4LZ = 3 -} XnStreamMiscCompressionFormat; - -/** The different types of audio stream compression formats. */ -typedef XN_OLD_IO_API enum { - /** Disable the audio buffer. */ - XN_COMPRESSED_AUDIO_FORMAT_SKIP = 0, - /** Uncompressed. */ - XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED = 1, -} XnStreamAudioCompressionFormat; - -/** The default depth compression format. */ -#define XN_STREAM_DEFAULT_DEPTH_COMPRESSION_FORMAT XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE -/** The default image compression format. */ -#define XN_STREAM_DEFAULT_IMAGE_COMPRESSION_FORMAT XN_COMPRESSED_IMAGE_FORMAT_JPEG -/** The default misc compression format. */ -#define XN_STREAM_DEFAULT_MISC_COMPRESSION_FORMAT XN_COMPRESSED_MISC_FORMAT_SKIP -/** The default audio compression format. */ -#define XN_STREAM_DEFAULT_AUDIO_COMPRESSION_FORMAT XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED - - -//--------------------------------------------------------------------------- -// Structures -//--------------------------------------------------------------------------- -#pragma pack (push, 1) - -typedef XN_OLD_IO_API struct Shift2DepthStruct -{ - /** True if shift-to-depth params are available. */ - XnBool bShift2DepthData; - XnUInt32 nConstShift; - XnUInt32 nPixelSizeFactor; - /** The maximum possible shift value from this device. */ - XnUInt32 nMaxShiftValue; - /** The maximum possible depth from this device (as opposed to a cut-off). */ - XnUInt32 nMaxDepthValue; - XnUInt32 nParamCoeff; - XnUInt32 nShiftScale; -} Shift2DepthStruct; - -/** - * Describes the Xiron stream properties. - * It is defined once per opened stream and will be filled automatically by the device if empty. - */ -typedef XN_OLD_IO_API struct XnStreamProperties -{ - /** A bit mask of Xiron stream flags. */ - XN_STREAM_FLAGS_TYPE nStreamFlags; - - /** The number of frames in this Xiron stream. */ - XnUInt32 nNumOfFrames; - - /** The number of frames per second. Legal values are: 15-60.*/ - XnUInt8 nDepthFramesPerSecond; - XnUInt8 nImageFramesPerSecond; - - /** Padding. */ - XnUInt16 nReserved; - - /** The depth buffer format. */ - XnStreamDepthFormat DepthFormat; - /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ - XnUInt16 nDepthXRes; - /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ - XnUInt16 nDepthYRes; - /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nDepthBufferSize; - /** The depth buffer element size in bits. */ - XnUInt32 nDepthTypeBitSize; - - /** The minimum depth value in the depth buffer. */ - XnDepthPixel nDepthMinValue; - /** The maximum depth value in the depth buffer. */ - XnDepthPixel nDepthMaxValue; - /** The value that represents no-sample in the depth buffer. */ - XnDepthPixel nDepthNoSampleValue; - /** The value that represents shadow in the depth buffer. */ - XnDepthPixel nDepthShadowValue; - - /** The image buffer format. */ - XnStreamImageFormat ImageFormat; - /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ - XnUInt16 nImageXRes; - /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ - XnUInt16 nImageYRes; - /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nImageBufferSize; - /** The image buffer element size in bits. */ - XnUInt32 nImageTypeBitSize; - - /** The audio buffer format. */ - XnStreamAudioFormat AudioFormat; - /** The number of audio channels. */ - XnUInt8 nAudioNumOfChannels; - - /** Padding. */ - XnUInt8 nReserved2; - XnUInt16 nReserved3; - - /** The audio sample rate. */ - XnSampleRate nAudioSampleRate; - /** The audio buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nAudioBufferSize; - /** Audio read mode. */ - XnAudioReadMode AudioReadMode; - /** When AudioReadMode is XN_AUDIO_READ_STREAM, this member is the number of bytes that will be read each time. */ - XnUInt32 nAudioReadChunkSize; - - /** The miscellaneous buffer format. */ - XnStreamMiscFormat MiscFormat; - /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nMiscBufferSize; - /** The miscellaneous buffer element size in bits. */ - XnUInt32 nMiscTypeBitSize; - - /** The zero plane distance in depth units. */ - XnDepthPixel nZeroPlaneDistance; - - /** Padding. */ - XnUInt16 nReserved4; - - /** The zero plane pixel size */ - XnFloat fZeroPlanePixelSize; - /** The distance between the emitter and the Depth Cmos */ - XnFloat fEmitterDCmosDistance; - - /** Information relevant for Shift2Depth */ - Shift2DepthStruct Shift2DepthData; - -} XnStreamProperties; - -/** - * Describes the Xiron stream frame buffer that actually holds the raw data. - * Can be reused between different streams as long as it is big enough to store the data. - */ -typedef XN_OLD_IO_API struct XnStreamFrameBuffer -{ - /** The stream properties that were used to create this frame buffer. */ - XnStreamProperties StreamProperties; - - /** A pointer to the depth buffer. */ - XnDepthPixel* pDepthBuffer; - /** The depth buffer size in bytes. */ - XnUInt32 nDepthBufferSize; - - /** A pointer to the image buffer. */ - XnUInt8* pImageBuffer; - /** The image buffer size in bytes. */ - XnUInt32 nImageBufferSize; - - /** A pointer to the miscellaneous buffer. */ - XN_MISC_TYPE* pMiscBuffer; - /** The miscellaneous buffer size in bytes. */ - XnUInt32 nMiscBufferSize; - - /** A pointer to the audio buffer. */ - XnUChar* pAudioBuffer; - /** The audio buffer size in bytes. */ - XnUInt32 nAudioBufferSize; - /** The actual number of bytes written in the audio buffer. */ - XnUInt32 nAudioWrittenBytes; - - void* pInternalData; -} XnStreamFrameBuffer; - -/** - * Describes the Xiron stream frame properties. - * Every single frame of the stream should have one defined. - */ -typedef XN_OLD_IO_API struct XnStreamFrameProperties -{ - union - { - /** Backward compatibility - general ID equals the Depth Frame ID */ - XnUInt32 nFrameID; - /** The frame id of this stream frame. */ - XnInt32 nDepthFrameID; - }; - XnUInt32 nImageFrameID; - - union - { - /** Backward compatibility - general TimeStamp equals the Depth Frame ID */ - XnUInt64 nTimeStamp; - /** The creation time of this stream frame. */ - XnUInt64 nDepthTimeStamp; - }; - XnUInt64 nImageTimeStamp; - - /** The creation time of last audio packet in the buffer. */ - XnUInt64 nAudioTimeStamp; -} XnStreamFrameProperties; - -#pragma pack (pop) - -#pragma warning (pop) - -#endif //_XN_STREAM_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + +#ifndef _XN_STREAM_H_ +#define _XN_STREAM_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +#if (!defined _XN_IO_BC && !defined XN_USE_DEVICE_3_6) + #define XN_OLD_IO_API XN_API_DEPRECATED("This is old XnIO API. Please use XnVDevice instead.") + #define _XN_DEPRECATE_OLD_IO +#else + #define XN_OLD_IO_API +#endif + +// some structs here that are deprecated holds other deprecated, so diable warnings +#pragma warning (push) +#pragma warning (disable: XN_DEPRECATED_WARNING_IDS) + +/** The stream flag unit. */ +#define XN_STREAM_FLAGS_TYPE XnInt32 + +/** Perform a horizontal flip on the output buffers. */ +#define XN_STREAM_FLAG_MIRROR 1 + +#ifdef _XN_DEPRECATE_OLD_IO +#pragma deprecated ("XN_STREAM_FLAGS_TYPE", "XN_STREAM_FLAG_MIRROR") +#endif + +typedef XN_OLD_IO_API enum XnAudioReadMode +{ + XN_AUDIO_READ_FRAMES, + XN_AUDIO_READ_STREAM +} XnAudioReadMode; + +//--------------------------------------------------------------------------- +// Stream Buffer Formats +//--------------------------------------------------------------------------- +/** The different types of depth buffers. */ +typedef XN_OLD_IO_API enum { + /** Disable the depth buffer. */ + XN_DEPTH_FORMAT_DISABLED = 0, + /** 10-bit depth values stored in a 16-bit buffer. */ + XN_DEPTH_FORMAT_RAW10 = 1, + /** 12-bit depth values stored in a 16-bit buffer. */ + XN_DEPTH_FORMAT_RAW12 = 2, + /** Shift values, in pixels. */ + XN_DEPTH_FORMAT_SHIFTS = 3, +} XnStreamDepthFormat; + +/** The different types of image buffers. */ +typedef XN_OLD_IO_API enum { + /** Disable the image buffer. */ + XN_IMAGE_FORMAT_DISABLED = 0, + /** Grayscale only image buffer. */ + XN_IMAGE_FORMAT_GRAYSCALE8 = 1, + /** Red, Green and Blue image buffer. */ + XN_IMAGE_FORMAT_RGB24 = 2, + /** YUV422 (uyvy) image buffer. */ + XN_IMAGE_FORMAT_YUV422 = 3, +} XnStreamImageFormat; + +/** The different types of audio buffers. */ +typedef XN_OLD_IO_API enum XnStreamAudioFormat { + /** Disable the audio buffer. */ + XN_AUDIO_FORMAT_DISABLED = 0, + /** PCM audio buffer. */ + XN_AUDIO_FORMAT_PCM, +} XnStreamAudioFormat; + +/** The different types of miscellaneous buffers. */ +typedef XN_OLD_IO_API enum { + /** Disable the miscellaneous buffer. */ + XN_MISC_FORMAT_DISABLED = 0, + /** 4-bit confidence map stored in an 8-bit buffer. */ + XN_MISC_FORMAT_CONFIDENCE_MAP = 1 +} XnStreamMiscFormat; + +/** The default depth buffer format. */ +#define XN_STREAM_DEFAULT_DEPTH_FORMAT XN_DEPTH_FORMAT_RAW12 +/** The default image buffer format. */ +#define XN_STREAM_DEFAULT_IMAGE_FORMAT XN_IMAGE_FORMAT_RGB24 +/** The default miscellaneous buffer format. */ +#define XN_STREAM_DEFAULT_MISC_FORMAT XN_MISC_FORMAT_CONFIDENCE_MAP + +#ifdef _XN_DEPRECATE_OLD_IO +#pragma deprecated (XN_STREAM_DEFAULT_DEPTH_FORMAT, XN_STREAM_DEFAULT_IMAGE_FORMAT, XN_STREAM_DEFAULT_MISC_FORMAT) +#endif + +//--------------------------------------------------------------------------- +// Stream Compressions +//--------------------------------------------------------------------------- + +/** The different types of depth stream compression formats. */ +typedef XN_OLD_IO_API enum { + /** Disable the depth buffer. */ + XN_COMPRESSED_DEPTH_FORMAT_SKIP = 0, + /** Uncompressed. */ + XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED = 1, + /** 16-bit Prime Sense Lossless Depth Compression. */ + XN_COMPRESSED_DEPTH_FORMAT_16Z = 2, + /** 16-bit Prime Sense Lossless Depth Compression + embedded tables. */ + XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE = 4, +} XnStreamDepthCompressionFormat; + +/** The different types of image stream compression formats. */ +typedef XN_OLD_IO_API enum { + /** Disable the image buffer. */ + XN_COMPRESSED_IMAGE_FORMAT_SKIP = 0, + /** Uncompressed. */ + XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED = 1, + /** 8-bit Prime Sense Lossless Image Compression. */ + XN_COMPRESSED_IMAGE_FORMAT_8Z = 2, + /** JPEG compression (default) */ + XN_COMPRESSED_IMAGE_FORMAT_JPEG = 3, + /** IR packed 10 bit */ + XN_COMPRESSED_IMAGE_FORMAT_IR10 = 4, +} XnStreamImageCompressionFormat; + +/** The different types of miscellaneous stream compression formats. */ +typedef XN_OLD_IO_API enum { + /** Disable the miscellaneous buffer. */ + XN_COMPRESSED_MISC_FORMAT_SKIP = 0, + /** Uncompressed. */ + XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED = 1, + /** 4-bit Confidence map. */ + XN_COMPRESSED_MISC_FORMAT_CONF4 = 2, + /** 4-bit Confidence map + simple LZ compression (UNSUPPORTED!). */ + XN_COMPRESSED_MISC_FORMAT_CONF4LZ = 3 +} XnStreamMiscCompressionFormat; + +/** The different types of audio stream compression formats. */ +typedef XN_OLD_IO_API enum { + /** Disable the audio buffer. */ + XN_COMPRESSED_AUDIO_FORMAT_SKIP = 0, + /** Uncompressed. */ + XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED = 1, +} XnStreamAudioCompressionFormat; + +/** The default depth compression format. */ +#define XN_STREAM_DEFAULT_DEPTH_COMPRESSION_FORMAT XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE +/** The default image compression format. */ +#define XN_STREAM_DEFAULT_IMAGE_COMPRESSION_FORMAT XN_COMPRESSED_IMAGE_FORMAT_JPEG +/** The default misc compression format. */ +#define XN_STREAM_DEFAULT_MISC_COMPRESSION_FORMAT XN_COMPRESSED_MISC_FORMAT_SKIP +/** The default audio compression format. */ +#define XN_STREAM_DEFAULT_AUDIO_COMPRESSION_FORMAT XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED + + +//--------------------------------------------------------------------------- +// Structures +//--------------------------------------------------------------------------- +#pragma pack (push, 1) + +typedef XN_OLD_IO_API struct Shift2DepthStruct +{ + /** True if shift-to-depth params are available. */ + XnBool bShift2DepthData; + XnUInt32 nConstShift; + XnUInt32 nPixelSizeFactor; + /** The maximum possible shift value from this device. */ + XnUInt32 nMaxShiftValue; + /** The maximum possible depth from this device (as opposed to a cut-off). */ + XnUInt32 nMaxDepthValue; + XnUInt32 nParamCoeff; + XnUInt32 nShiftScale; +} Shift2DepthStruct; + +/** + * Describes the Xiron stream properties. + * It is defined once per opened stream and will be filled automatically by the device if empty. + */ +typedef XN_OLD_IO_API struct XnStreamProperties +{ + /** A bit mask of Xiron stream flags. */ + XN_STREAM_FLAGS_TYPE nStreamFlags; + + /** The number of frames in this Xiron stream. */ + XnUInt32 nNumOfFrames; + + /** The number of frames per second. Legal values are: 15-60.*/ + XnUInt8 nDepthFramesPerSecond; + XnUInt8 nImageFramesPerSecond; + + /** Padding. */ + XnUInt16 nReserved; + + /** The depth buffer format. */ + XnStreamDepthFormat DepthFormat; + /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ + XnUInt16 nDepthXRes; + /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ + XnUInt16 nDepthYRes; + /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nDepthBufferSize; + /** The depth buffer element size in bits. */ + XnUInt32 nDepthTypeBitSize; + + /** The minimum depth value in the depth buffer. */ + XnDepthPixel nDepthMinValue; + /** The maximum depth value in the depth buffer. */ + XnDepthPixel nDepthMaxValue; + /** The value that represents no-sample in the depth buffer. */ + XnDepthPixel nDepthNoSampleValue; + /** The value that represents shadow in the depth buffer. */ + XnDepthPixel nDepthShadowValue; + + /** The image buffer format. */ + XnStreamImageFormat ImageFormat; + /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ + XnUInt16 nImageXRes; + /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ + XnUInt16 nImageYRes; + /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nImageBufferSize; + /** The image buffer element size in bits. */ + XnUInt32 nImageTypeBitSize; + + /** The audio buffer format. */ + XnStreamAudioFormat AudioFormat; + /** The number of audio channels. */ + XnUInt8 nAudioNumOfChannels; + + /** Padding. */ + XnUInt8 nReserved2; + XnUInt16 nReserved3; + + /** The audio sample rate. */ + XnSampleRate nAudioSampleRate; + /** The audio buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nAudioBufferSize; + /** Audio read mode. */ + XnAudioReadMode AudioReadMode; + /** When AudioReadMode is XN_AUDIO_READ_STREAM, this member is the number of bytes that will be read each time. */ + XnUInt32 nAudioReadChunkSize; + + /** The miscellaneous buffer format. */ + XnStreamMiscFormat MiscFormat; + /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nMiscBufferSize; + /** The miscellaneous buffer element size in bits. */ + XnUInt32 nMiscTypeBitSize; + + /** The zero plane distance in depth units. */ + XnDepthPixel nZeroPlaneDistance; + + /** Padding. */ + XnUInt16 nReserved4; + + /** The zero plane pixel size */ + XnFloat fZeroPlanePixelSize; + /** The distance between the emitter and the Depth Cmos */ + XnFloat fEmitterDCmosDistance; + + /** Information relevant for Shift2Depth */ + Shift2DepthStruct Shift2DepthData; + +} XnStreamProperties; + +/** + * Describes the Xiron stream frame buffer that actually holds the raw data. + * Can be reused between different streams as long as it is big enough to store the data. + */ +typedef XN_OLD_IO_API struct XnStreamFrameBuffer +{ + /** The stream properties that were used to create this frame buffer. */ + XnStreamProperties StreamProperties; + + /** A pointer to the depth buffer. */ + XnDepthPixel* pDepthBuffer; + /** The depth buffer size in bytes. */ + XnUInt32 nDepthBufferSize; + + /** A pointer to the image buffer. */ + XnUInt8* pImageBuffer; + /** The image buffer size in bytes. */ + XnUInt32 nImageBufferSize; + + /** A pointer to the miscellaneous buffer. */ + XN_MISC_TYPE* pMiscBuffer; + /** The miscellaneous buffer size in bytes. */ + XnUInt32 nMiscBufferSize; + + /** A pointer to the audio buffer. */ + XnUChar* pAudioBuffer; + /** The audio buffer size in bytes. */ + XnUInt32 nAudioBufferSize; + /** The actual number of bytes written in the audio buffer. */ + XnUInt32 nAudioWrittenBytes; + + void* pInternalData; +} XnStreamFrameBuffer; + +/** + * Describes the Xiron stream frame properties. + * Every single frame of the stream should have one defined. + */ +typedef XN_OLD_IO_API struct XnStreamFrameProperties +{ + union + { + /** Backward compatibility - general ID equals the Depth Frame ID */ + XnUInt32 nFrameID; + /** The frame id of this stream frame. */ + XnInt32 nDepthFrameID; + }; + XnUInt32 nImageFrameID; + + union + { + /** Backward compatibility - general TimeStamp equals the Depth Frame ID */ + XnUInt64 nTimeStamp; + /** The creation time of this stream frame. */ + XnUInt64 nDepthTimeStamp; + }; + XnUInt64 nImageTimeStamp; + + /** The creation time of last audio packet in the buffer. */ + XnUInt64 nAudioTimeStamp; +} XnStreamFrameProperties; + +#pragma pack (pop) + +#pragma warning (pop) + +#endif //_XN_STREAM_H_ diff --git a/Include/XnStreamData.h b/Include/XnStreamData.h index 89e6e66..d8aad1f 100644 --- a/Include/XnStreamData.h +++ b/Include/XnStreamData.h @@ -1,121 +1,121 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_OUTPUT_H__ -#define __XN_STREAM_OUTPUT_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -struct XnStreamDataInternal; // Forward Declaration -typedef struct XnStreamDataInternal XnStreamDataInternal; - -typedef enum XnStreamDataUpdateMode -{ - /* Stream output object will automatically reallocate buffer if needed. */ - XN_STREAM_DATA_UPDATE_AUTOMATICALLY, - /* Stream output will let the client a chance to reallocate buffer. */ - XN_STREAM_DATA_UPDATE_NOTIFY, - /* Stream output will do nothing. */ - XN_STREAM_DATA_UPDATE_OFF, -} XnStreamDataUpdateMode; - -typedef struct XnStreamData -{ - /* Name of the stream this object is related to. */ - XnChar StreamName[XN_DEVICE_MAX_STRING_LENGTH]; - /* Timestamp of current data. */ - XnUInt64 nTimestamp; - /* Frame ID of current data. For non-frame-based streams, this value is undetermined. */ - XnUInt32 nFrameID; - /* A pointer to the data itself. This pointer should be converted according to the stream. */ - void* pData; - /* The number of bytes written in the data buffer. */ - XnUInt32 nDataSize; - /* True when then data is new, False otherwise. */ - XnBool bIsNew; - /* Internal use only. */ - XnStreamDataInternal* pInternal; -} XnStreamData; - -typedef void (XN_CALLBACK_TYPE* XnStreamOutputNotificationCallback)(XnStreamData* pStreamOutput, void* pCallbackData, XnUInt32 nNeededSize); - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- - -/** -* Creates a new stream output object. -* -* @param ppStreamOutput [out] A pointer to the newly created object. -* @param StreamName [in] The name of the stream that this buffer will be used for. -* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. -*/ -XN_DDK_API XnStatus XnStreamDataCreate(XnStreamData** ppStreamOutput, const XnChar* StreamName, XnUInt32 nAllocSize); - -/** -* Destroys a previously created stream output object. -* -* @param ppStreamOutput [in] A previously created stream output object. -*/ -XN_DDK_API XnStatus XnStreamDataDestroy(XnStreamData** ppStreamOutput); - -/** -* Updates the allocated size of a stream output object. -* -* @param pStreamOutput [in] The stream output object. -* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. -*/ -XN_DDK_API XnStatus XnStreamDataUpdateSize(XnStreamData* pStreamOutput, XnUInt32 nAllocSize); - -/** -* Sets the update mode of a stream output object. -* -* @param pStreamOutput [in] A stream output object. -* @param UpdateMode [in] The update mode to use. -* @param Callback [in] A callback to call when an update is required. if update mode is not NOTIFY, this can be null. -* @param pCallbackData [in] [Optional] Data to be passed to the callback function. -*/ -XN_DDK_API XnStatus XnStreamDataSetUpdateMode(XnStreamData* pStreamOutput, XnStreamDataUpdateMode UpdateMode, XnStreamOutputNotificationCallback Callback, void* pCallbackData); - -/** -* Checks if the stream output object has enough space for data. -* -* @param pStreamOutput [in] A stream output object. -* @param nNeededSize [in] The number of needed bytes. -*/ -XN_DDK_API XnStatus XnStreamDataCheckSize(XnStreamData* pStreamOutput, XnUInt32 nNeededSize); - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_OUTPUT_H__ +#define __XN_STREAM_OUTPUT_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +struct XnStreamDataInternal; // Forward Declaration +typedef struct XnStreamDataInternal XnStreamDataInternal; + +typedef enum XnStreamDataUpdateMode +{ + /* Stream output object will automatically reallocate buffer if needed. */ + XN_STREAM_DATA_UPDATE_AUTOMATICALLY, + /* Stream output will let the client a chance to reallocate buffer. */ + XN_STREAM_DATA_UPDATE_NOTIFY, + /* Stream output will do nothing. */ + XN_STREAM_DATA_UPDATE_OFF, +} XnStreamDataUpdateMode; + +typedef struct XnStreamData +{ + /* Name of the stream this object is related to. */ + XnChar StreamName[XN_DEVICE_MAX_STRING_LENGTH]; + /* Timestamp of current data. */ + XnUInt64 nTimestamp; + /* Frame ID of current data. For non-frame-based streams, this value is undetermined. */ + XnUInt32 nFrameID; + /* A pointer to the data itself. This pointer should be converted according to the stream. */ + void* pData; + /* The number of bytes written in the data buffer. */ + XnUInt32 nDataSize; + /* True when then data is new, False otherwise. */ + XnBool bIsNew; + /* Internal use only. */ + XnStreamDataInternal* pInternal; +} XnStreamData; + +typedef void (XN_CALLBACK_TYPE* XnStreamOutputNotificationCallback)(XnStreamData* pStreamOutput, void* pCallbackData, XnUInt32 nNeededSize); + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- + +/** +* Creates a new stream output object. +* +* @param ppStreamOutput [out] A pointer to the newly created object. +* @param StreamName [in] The name of the stream that this buffer will be used for. +* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. +*/ +XN_DDK_API XnStatus XnStreamDataCreate(XnStreamData** ppStreamOutput, const XnChar* StreamName, XnUInt32 nAllocSize); + +/** +* Destroys a previously created stream output object. +* +* @param ppStreamOutput [in] A previously created stream output object. +*/ +XN_DDK_API XnStatus XnStreamDataDestroy(XnStreamData** ppStreamOutput); + +/** +* Updates the allocated size of a stream output object. +* +* @param pStreamOutput [in] The stream output object. +* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. +*/ +XN_DDK_API XnStatus XnStreamDataUpdateSize(XnStreamData* pStreamOutput, XnUInt32 nAllocSize); + +/** +* Sets the update mode of a stream output object. +* +* @param pStreamOutput [in] A stream output object. +* @param UpdateMode [in] The update mode to use. +* @param Callback [in] A callback to call when an update is required. if update mode is not NOTIFY, this can be null. +* @param pCallbackData [in] [Optional] Data to be passed to the callback function. +*/ +XN_DDK_API XnStatus XnStreamDataSetUpdateMode(XnStreamData* pStreamOutput, XnStreamDataUpdateMode UpdateMode, XnStreamOutputNotificationCallback Callback, void* pCallbackData); + +/** +* Checks if the stream output object has enough space for data. +* +* @param pStreamOutput [in] A stream output object. +* @param nNeededSize [in] The number of needed bytes. +*/ +XN_DDK_API XnStatus XnStreamDataCheckSize(XnStreamData* pStreamOutput, XnUInt32 nNeededSize); + #endif //__XN_STREAM_OUTPUT_H__ \ No newline at end of file diff --git a/Include/XnStreamDataSet.h b/Include/XnStreamDataSet.h index 4155ba7..e6d3064 100644 --- a/Include/XnStreamDataSet.h +++ b/Include/XnStreamDataSet.h @@ -1,101 +1,101 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_OUTPUT_SET_H__ -#define __XN_STREAM_OUTPUT_SET_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -struct XnStreamDataSet; // Forward Declaration -typedef struct XnStreamDataSet XnStreamDataSet; - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- - -/** -* Creates a new stream output set object. -* -* @param ppStreamOutputSet [out] A pointer to the newly created object. -*/ -XN_DDK_API XnStatus XnStreamDataSetCreate(XnStreamDataSet** ppStreamOutputSet); - -/** -* Destroys a previously created stream output set object. -* -* @param ppStreamOutputSet [in] A previously created stream output set object. -*/ -XN_DDK_API XnStatus XnStreamDataSetDestroy(XnStreamDataSet** ppStreamOutputSet); - -/** -* Adds a stream output object to the set. A set cannot contain more than one stream output for the same stream. -* -* @param pStreamOutputSet [in] The set. -* @param pStreamOutput [in] A stream output object to add to the set -*/ -XN_DDK_API XnStatus XnStreamDataSetAdd(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput); - -/** -* Removes a stream output object from the set. -* -* @param pStreamOutputSet [in] The set. -* @param pStreamOutput [in] The stream output set to remove. -*/ -XN_DDK_API XnStatus XnStreamDataSetRemove(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput); - -/** -* Removes a stream output object from the set, by name. -* -* @param pStreamOutputSet [in] The set. -* @param StreamName [in] The stream which its object should be removed. -*/ -XN_DDK_API XnStatus XnStreamDataSetRemoveByName(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName); - -/** -* Gets a stream output object from the set by the name of its stream. -* -* @param pStreamOutputSet [in] The set. -* @param StreamName [in] The stream name. -* @param ppStreamOutput [out] The stream output object related to that stream. -*/ -XN_DDK_API XnStatus XnStreamDataSetGet(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName, XnStreamData** ppStreamOutput); - -/** -* Gets the set as an array of pointers to objects. -* -* @param pStreamOutputSet [in] The set. -* @param apStreamOutputs [out] An array of pointers to be filled. -* @param pnCount [in/out] The size of the array. -*/ -XN_DDK_API XnStatus XnStreamDataSetCopyToArray(const XnStreamDataSet* pStreamOutputSet, XnStreamData** apStreamOutputs, XnUInt32* pnCount); - -#endif //__XN_STREAM_OUTPUT_SET_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_OUTPUT_SET_H__ +#define __XN_STREAM_OUTPUT_SET_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +struct XnStreamDataSet; // Forward Declaration +typedef struct XnStreamDataSet XnStreamDataSet; + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- + +/** +* Creates a new stream output set object. +* +* @param ppStreamOutputSet [out] A pointer to the newly created object. +*/ +XN_DDK_API XnStatus XnStreamDataSetCreate(XnStreamDataSet** ppStreamOutputSet); + +/** +* Destroys a previously created stream output set object. +* +* @param ppStreamOutputSet [in] A previously created stream output set object. +*/ +XN_DDK_API XnStatus XnStreamDataSetDestroy(XnStreamDataSet** ppStreamOutputSet); + +/** +* Adds a stream output object to the set. A set cannot contain more than one stream output for the same stream. +* +* @param pStreamOutputSet [in] The set. +* @param pStreamOutput [in] A stream output object to add to the set +*/ +XN_DDK_API XnStatus XnStreamDataSetAdd(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput); + +/** +* Removes a stream output object from the set. +* +* @param pStreamOutputSet [in] The set. +* @param pStreamOutput [in] The stream output set to remove. +*/ +XN_DDK_API XnStatus XnStreamDataSetRemove(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput); + +/** +* Removes a stream output object from the set, by name. +* +* @param pStreamOutputSet [in] The set. +* @param StreamName [in] The stream which its object should be removed. +*/ +XN_DDK_API XnStatus XnStreamDataSetRemoveByName(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName); + +/** +* Gets a stream output object from the set by the name of its stream. +* +* @param pStreamOutputSet [in] The set. +* @param StreamName [in] The stream name. +* @param ppStreamOutput [out] The stream output object related to that stream. +*/ +XN_DDK_API XnStatus XnStreamDataSetGet(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName, XnStreamData** ppStreamOutput); + +/** +* Gets the set as an array of pointers to objects. +* +* @param pStreamOutputSet [in] The set. +* @param apStreamOutputs [out] An array of pointers to be filled. +* @param pnCount [in/out] The size of the array. +*/ +XN_DDK_API XnStatus XnStreamDataSetCopyToArray(const XnStreamDataSet* pStreamOutputSet, XnStreamData** apStreamOutputs, XnUInt32* pnCount); + +#endif //__XN_STREAM_OUTPUT_SET_H__ diff --git a/Include/XnStreamFormats.h b/Include/XnStreamFormats.h index 8308e91..42f0134 100644 --- a/Include/XnStreamFormats.h +++ b/Include/XnStreamFormats.h @@ -1,85 +1,85 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_STREAM_FORMATS_H__ -#define __XN_STREAM_FORMATS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Pixel Types -//--------------------------------------------------------------------------- -/** The basic depth buffer unit. */ -//#define XN_DEPTH_TYPE XnUInt16 -/** The basic image buffer unit. */ -//#define XN_IMAGE_TYPE XnUInt8 -/** The basic miscellaneous buffer unit. */ -#define XN_MISC_TYPE XnUInt8 -/** The basic audio buffer unit. */ -#define XN_AUDIO_TYPE XnUInt8 -/** The miscellaneous confidence map buffer unit. */ -#define XN_MISC_CONF_TYPE XnUInt8 - -//--------------------------------------------------------------------------- -// Formats -//--------------------------------------------------------------------------- - -/** The different types of stream outputs. */ -typedef enum -{ - XN_OUTPUT_FORMAT_SHIFT_VALUES = 0, - XN_OUTPUT_FORMAT_DEPTH_VALUES = 1, - XN_OUTPUT_FORMAT_GRAYSCALE8 = 2, - XN_OUTPUT_FORMAT_GRAYSCALE16 = 3, - XN_OUTPUT_FORMAT_YUV422 = 4, - XN_OUTPUT_FORMAT_RGB24 = 5, - XN_OUTPUT_FORMAT_JPEG = 6, - XN_OUTPUT_FORMAT_PCM = 7, - XN_OUTPUT_FORMATS_COUNT, -} XnOutputFormats; - -typedef enum -{ - /** Data is stored uncompressed. */ - XN_COMPRESSION_NONE = 0, - /** Data is compressed using PS lossless 16-bit depth compression. */ - XN_COMPRESSION_16Z = 1, - /** Data is compressed using PS lossless 16-bit depth compression with embedded tables. */ - XN_COMPRESSION_16Z_EMB_TABLE = 2, - /** Data is compressed using PS lossless 8-bit image compression (for grayscale). */ - XN_COMPRESSION_COLOR_8Z = 3, - /** Data is compressed using JPEG. */ - XN_COMPRESSION_JPEG = 4, - /** Data is packed in 10-bit values. */ - XN_COMPRESSION_10BIT_PACKED = 5, -} XnCompressionFormats; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_STREAM_FORMATS_H__ +#define __XN_STREAM_FORMATS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Pixel Types +//--------------------------------------------------------------------------- +/** The basic depth buffer unit. */ +//#define XN_DEPTH_TYPE XnUInt16 +/** The basic image buffer unit. */ +//#define XN_IMAGE_TYPE XnUInt8 +/** The basic miscellaneous buffer unit. */ +#define XN_MISC_TYPE XnUInt8 +/** The basic audio buffer unit. */ +#define XN_AUDIO_TYPE XnUInt8 +/** The miscellaneous confidence map buffer unit. */ +#define XN_MISC_CONF_TYPE XnUInt8 + +//--------------------------------------------------------------------------- +// Formats +//--------------------------------------------------------------------------- + +/** The different types of stream outputs. */ +typedef enum +{ + XN_OUTPUT_FORMAT_SHIFT_VALUES = 0, + XN_OUTPUT_FORMAT_DEPTH_VALUES = 1, + XN_OUTPUT_FORMAT_GRAYSCALE8 = 2, + XN_OUTPUT_FORMAT_GRAYSCALE16 = 3, + XN_OUTPUT_FORMAT_YUV422 = 4, + XN_OUTPUT_FORMAT_RGB24 = 5, + XN_OUTPUT_FORMAT_JPEG = 6, + XN_OUTPUT_FORMAT_PCM = 7, + XN_OUTPUT_FORMATS_COUNT, +} XnOutputFormats; + +typedef enum +{ + /** Data is stored uncompressed. */ + XN_COMPRESSION_NONE = 0, + /** Data is compressed using PS lossless 16-bit depth compression. */ + XN_COMPRESSION_16Z = 1, + /** Data is compressed using PS lossless 16-bit depth compression with embedded tables. */ + XN_COMPRESSION_16Z_EMB_TABLE = 2, + /** Data is compressed using PS lossless 8-bit image compression (for grayscale). */ + XN_COMPRESSION_COLOR_8Z = 3, + /** Data is compressed using JPEG. */ + XN_COMPRESSION_JPEG = 4, + /** Data is packed in 10-bit values. */ + XN_COMPRESSION_10BIT_PACKED = 5, +} XnCompressionFormats; + #endif //__XN_STREAM_FORMATS_H__ \ No newline at end of file diff --git a/Include/XnStreamParams.h b/Include/XnStreamParams.h index ac42799..950afd1 100644 --- a/Include/XnStreamParams.h +++ b/Include/XnStreamParams.h @@ -1,530 +1,532 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_STREAM_PARAMS_H_ -#define _XN_STREAM_PARAMS_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -/** The maximum permitted Xiron device name string length. */ -#define XN_DEVICE_MAX_STRING_LENGTH 200 - -//--------------------------------------------------------------------------- -// Modules Names -//--------------------------------------------------------------------------- -#define XN_MODULE_NAME_DEVICE "Device" - -#define XN_MODULE_NAME_FIXED_PARAMS "FixedParams" -#define XN_MODULE_NAME_SHIFTS "Shifts" - -#ifndef XN_USE_DEVICE_3_6 -#pragma deprecated ("XN_MODULE_NAME_FIXED_PARAMS", "XN_MODULE_NAME_SHIFTS") -#endif - -//--------------------------------------------------------------------------- -// Streams Types -//--------------------------------------------------------------------------- -#define XN_STREAM_TYPE_DEPTH "Depth" -#define XN_STREAM_TYPE_IMAGE "Image" -#define XN_STREAM_TYPE_IR "IR" -#define XN_STREAM_TYPE_AUDIO "Audio" - -//--------------------------------------------------------------------------- -// Streams Names -//--------------------------------------------------------------------------- -#define XN_STREAM_NAME_DEPTH XN_STREAM_TYPE_DEPTH -#define XN_STREAM_NAME_IMAGE XN_STREAM_TYPE_IMAGE -#define XN_STREAM_NAME_IR XN_STREAM_TYPE_IR -#define XN_STREAM_NAME_AUDIO XN_STREAM_TYPE_AUDIO - -//--------------------------------------------------------------------------- -// General Properties -//--------------------------------------------------------------------------- -#define XN_STREAM_PROPERTY_TYPE "Type" -#define XN_STREAM_PROPERTY_IS_STREAM "IsStream" -#define XN_STREAM_PROPERTY_IS_FRAME_BASED "IsFrameBased" -#define XN_STREAM_PROPERTY_IS_PIXEL_BASED "IsPixelBased" -#define XN_STREAM_PROPERTY_IS_STREAMING "IsStreaming" - -/** Integer */ -#define XN_MODULE_PROPERTY_LOCK "Lock" - -//--------------------------------------------------------------------------- -// General Stream Properties -//--------------------------------------------------------------------------- -/** Integer */ -#define XN_STREAM_PROPERTY_STATE "State" -/** Integer */ -#define XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE "RequiredDataSize" -/** Integer */ -#define XN_STREAM_PROPERTY_FRAME_ID "FrameId" -/** Integer */ -#define XN_STREAM_PROPERTY_TIMESTAMP "Timestamp" -/** Integer */ -#define XN_STREAM_PROPERTY_IS_NEW_DATA "IsNew" -/** Integer (XnOutputFormats)*/ -#define XN_STREAM_PROPERTY_OUTPUT_FORMAT "OutputFormat" -/** General (void*) */ -#define XN_STREAM_PROPERTY_BUFFER "Buffer" -/** Integer */ -#define XN_STREAM_PROPERTY_BUFFER_SIZE "BufferSize" -/** Integer */ -#define XN_STREAM_PROPERTY_COMPRESSION "Compression" -/** String */ -#define XN_STREAM_PROPERTY_SHARED_BUFFER_NAME "SharedBufferName" -/** Boolean */ -#define XN_STREAM_PROPERTY_ACTUAL_READ_DATA "ActualReadData" - -/** Integer */ -#define XN_STREAM_PROPERTY_BUFFER_ALLOCATED_SIZE XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE - -#ifndef USE_DEVICE_3_6 -#pragma deprecated ("XN_STREAM_PROPERTY_BUFFER_ALLOCATED_SIZE") -#endif - -//--------------------------------------------------------------------------- -// Frame-Based Stream Properties (Depth, Image, IR) -//--------------------------------------------------------------------------- -/** Integer */ -#define XN_STREAM_PROPERTY_FPS "FPS" -/** Integer */ -#define XN_STREAM_PROPERTY_NUMBER_OF_FRAMES "NumberOfFrames" -/** Integer */ -#define XN_STREAM_PROPERTY_INPUT_FORMAT "InputFormat" -/** XnDynamicSizeBuffer */ -#define XN_STREAM_PROPERTY_LAST_RAW_FRAME "LastRawFrame" - -//--------------------------------------------------------------------------- -// Pixel-Based Stream Properties (Depth, Image, IR) -//--------------------------------------------------------------------------- -/** XnResolutions */ -#define XN_STREAM_PROPERTY_RESOLUTION "Resolution" -/** Integer */ -#define XN_STREAM_PROPERTY_X_RES "XRes" -/** Integer */ -#define XN_STREAM_PROPERTY_Y_RES "YRes" -/** Integer */ -#define XN_STREAM_PROPERTY_BYTES_PER_PIXEL "BytesPerPixel" -/** XnCropping */ -#define XN_STREAM_PROPERTY_CROPPING "Cropping" - -//--------------------------------------------------------------------------- -// Depth Specific Properties -//--------------------------------------------------------------------------- -/** Integer */ -#define XN_STREAM_PROPERTY_GAIN "Gain" -/** Integer */ -#define XN_STREAM_PROPERTY_HOLE_FILTER "HoleFilter" -/** Integer */ -#define XN_STREAM_PROPERTY_MIN_DEPTH "MinDepthValue" -/** Integer */ -#define XN_STREAM_PROPERTY_MAX_DEPTH "MaxDepthValue" -/** Integer */ -#define XN_STREAM_PROPERTY_SHADOW "ShadowValue" -/** Integer */ -#define XN_STREAM_PROPERTY_NO_SAMPLE "NoSampleValue" -/** Boolean */ -#define XN_STREAM_PROPERTY_REGISTRATION "Registration" -/** XnProcessingType */ -#define XN_STREAM_PROPERTY_REGISTRATION_TYPE "RegistrationType" -/** Boolean */ -#define XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED "WhiteBalancedEnabled" -/** XnDepthAGCBin* */ -#define XN_STREAM_PROPERTY_AGC_BIN "AGCBin" -/** Integer */ -#define XN_STREAM_PROPERTY_CONST_SHIFT "ConstShift" -/** Integer */ -#define XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR "PixelSizeFactor" -/** Integer */ -#define XN_STREAM_PROPERTY_MAX_SHIFT "MaxShift" -/** Integer */ -#define XN_STREAM_PROPERTY_PARAM_COEFF "ParamCoeff" -/** Integer */ -#define XN_STREAM_PROPERTY_SHIFT_SCALE "ShiftScale" -/** XN_DEPTH_TYPE[] */ -#define XN_STREAM_PROPERTY_S2D_TABLE "S2D" -/** XnUInt16[] */ -#define XN_STREAM_PROPERTY_D2S_TABLE "D2S" -/** Integer */ -#define XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH "DeviceMaxDepth" -/** XN_DEPTH_TYPE */ -#define XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE "ZPD" -/** Real */ -#define XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE "ZPPS" -/** Real */ -#define XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE "LDDIS" -/** Boolean */ -#define XN_STREAM_PROPERTY_GMC_MODE "GmcMode" - -//--------------------------------------------------------------------------- -// Shifts Properties (up to v3.6) -//--------------------------------------------------------------------------- -/** Integer */ -#define XN_MODULE_PROPERTY_CONST_SHIFT XN_STREAM_PROPERTY_CONST_SHIFT -/** Integer */ -#define XN_MODULE_PROPERTY_PIXEL_SIZE_FACTOR XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR -/** Integer */ -#define XN_MODULE_PROPERTY_MAX_SHIFT XN_STREAM_PROPERTY_MAX_SHIFT -/** Integer */ -#define XN_MODULE_PROPERTY_PARAM_COEFF XN_STREAM_PROPERTY_PARAM_COEFF -/** Integer */ -#define XN_MODULE_PROPERTY_SHIFT_SCALE XN_STREAM_PROPERTY_SHIFT_SCALE -/** XN_DEPTH_TYPE[] */ -#define XN_MODULE_PROPERTY_S2D_TABLE XN_STREAM_PROPERTY_S2D_TABLE -/** XnUInt16[] */ -#define XN_MODULE_PROPERTY_D2S_TABLE XN_STREAM_PROPERTY_D2S_TABLE - -#ifndef XN_USE_DEVICE_3_6 -#pragma deprecated ("XN_MODULE_PROPERTY_CONST_SHIFT", "XN_MODULE_PROPERTY_PIXEL_SIZE_FACTOR", "XN_MODULE_PROPERTY_MAX_SHIFT") -#pragma deprecated ("XN_MODULE_PROPERTY_PARAM_COEFF", "XN_MODULE_PROPERTY_SHIFT_SCALE") -#pragma deprecated ("XN_MODULE_PROPERTY_S2D_TABLE", "XN_MODULE_PROPERTY_D2S_TABLE") -#endif - -//--------------------------------------------------------------------------- -// FixedParams Properties (up to v3.6) -//--------------------------------------------------------------------------- -/** XN_DEPTH_TYPE */ -#define XN_MODULE_PROPERTY_ZERO_PLANE_DISTANCE XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE -/** Real */ -#define XN_MODULE_PROPERTY_ZERO_PLANE_PIXEL_SIZE XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE -/** Real */ -#define XN_MODULE_PROPERTY_EMITTER_DCMOS_DISTANCE XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE - -#ifndef XN_USE_DEVICE_3_6 -#pragma deprecated ("XN_MODULE_PROPERTY_ZERO_PLANE_DISTANCE", "XN_MODULE_PROPERTY_ZERO_PLANE_PIXEL_SIZE", "XN_MODULE_PROPERTY_EMITTER_DCMOS_DISTANCE") -#endif - -//--------------------------------------------------------------------------- -// Image Specific Properties -//--------------------------------------------------------------------------- -/** Integer */ -#define XN_STREAM_PROPERTY_FLICKER "Flicker" -/** Integer */ -#define XN_STREAM_PROPERTY_QUALITY "Quality" - -//--------------------------------------------------------------------------- -// Audio Specific Properties -//--------------------------------------------------------------------------- -/** XnSampleRate */ -#define XN_STREAM_PROPERTY_SAMPLE_RATE "SampleRate" -/** Integer */ -#define XN_STREAM_PROPERTY_LEFT_CHANNEL_VOLUME "LeftChannelVolume" -/** Integer */ -#define XN_STREAM_PROPERTY_RIGHT_CHANNEL_VOLUME "RightChannelVolume" -/** Integer */ -#define XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS "NumOfChannels" -/** Boolean */ -#define XN_STREAM_PROPERTY_IS_STEREO "IsStereo" -/** Integer */ -#define XN_STREAM_PROPERTY_READ_MODE "ReadMode" -/** Integer */ -#define XN_STREAM_PROPERTY_READ_CHUNK_SIZE "ReadChunkSize" -/** Integer */ -#define XN_STREAM_PROPERTY_READ_SYNC "AudioReadSync" - -#ifndef XN_USE_DEVICE_3_6 -#pragma deprecated ("XN_STREAM_PROPERTY_READ_MODE", "XN_STREAM_PROPERTY_READ_SYNC") -#endif - -//--------------------------------------------------------------------------- -// DeviceParams Properties -//--------------------------------------------------------------------------- -/** XnSDKVersion */ -#define XN_MODULE_PROPERTY_SDK_VERSION "SDKVersion" -/** String */ -#define XN_MODULE_PROPERTY_DEVICE_NAME "DeviceName" -/** Integer (XnSensorUsbInterface) */ -#define XN_MODULE_PROPERTY_USB_INTERFACE "UsbInterface" -/** Integer */ -#define XN_MODULE_PROPERTY_NUMBER_OF_BUFFERS "NumberOfBuffers" -/** Boolean */ -#define XN_MODULE_PROPERTY_READ_ENDPOINT_1 "ReadEndpoint1" -/** Boolean */ -#define XN_MODULE_PROPERTY_READ_ENDPOINT_2 "ReadEndpoint2" -/** Boolean */ -#define XN_MODULE_PROPERTY_READ_ENDPOINT_3 "ReadEndpoint3" -/** Boolean */ -#define XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP "ResetSensorOnStartup" -/** String */ -#define XN_MODULE_PROPERTY_ID "ID" -/** String */ -#define XN_MODULE_PROPERTY_PRIMARY_STREAM "PrimaryStream" -/** Boolean */ -#define XN_MODULE_PROPERTY_MIRROR "Mirror" -/** Boolean */ -#define XN_MODULE_PROPERTY_READ_DATA "ReadData" -/** Integer */ -#define XN_MODULE_PROPERTY_READ_WRITE_MODE "ReadWriteMode" -/** Integer */ -#define XN_MODULE_PROPERTY_SHARE_MODE "ShareMode" -/** Boolean */ -#define XN_MODULE_PROPERTY_FRAME_DELAY "FrameDelay" -/** Boolean */ -#define XN_MODULE_PROPERTY_FRAME_SYNC "FrameSync" -/** XnCmosBlankingUnits */ -#define XN_MODULE_PROPERTY_CMOS_BLANKING_UNITS "CmosBlankingUnits" -/** XnCmosBlankingTime */ -#define XN_MODULE_PROPERTY_CMOS_BLANKING_TIME "CmosBlankingTime" -/** XnInnerParam */ -#define XN_MODULE_PROPERTY_FIRMWARE_PARAM "FirmwareParam" -/** XnVersions */ -#define XN_MODULE_PROPERTY_VERSION "Version" -/* XnDynamicSizeBuffer */ -#define XN_MODULE_PROPERTY_FIXED_PARAMS "FixedParams" -/** Integer */ -#define XN_MODULE_PROPERTY_RESET "Reset" -/** Integer */ -#define XN_MODULE_PROPERTY_FIRMWARE_MODE "FirmwareMode" -/** Boolean */ -#define XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS "HighResTimestamps" -/** Boolean */ -#define XN_MODULE_PROPERTY_CLOSE_STREAMS_ON_SHUTDOWN "CloseStreamsOnShutdown" -/** Integer */ -#define XN_MODULE_PROPERTY_SERVER_NO_CLIENTS_TIMEOUT "ServerNoClientsTimeout" -/** Integer */ -#define XN_MODULE_PROPERTY_SERVER_START_NEW_LOG_FILE "ServerStartNewLogFile" -/** Integer */ -#define XN_MODULE_PROPERTY_ERROR_STATE "ErrorState" -/** Boolean */ -#define XN_MODULE_PROPERTY_ENABLE_MULTI_PROCESS "EnableMultiProcess" - - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_PRIMARY_STREAM_ANY "Any" -#define XN_PRIMARY_STREAM_NONE "None" - -#define XN_MAX_LOG_SIZE (6*1024) - -#define XN_GAIN_AUTO 0U - -#define XN_QVGA_X_RES 320 -#define XN_QVGA_Y_RES 240 -#define XN_VGA_X_RES 640 -#define XN_VGA_Y_RES 480 -#define XN_SXGA_X_RES 1280 -#define XN_SXGA_Y_RES 1024 -#define XN_UXGA_X_RES 1600 -#define XN_UXGA_Y_RES 1200 - - -//--------------------------------------------------------------------------- -// Enums - values of various properties -//--------------------------------------------------------------------------- -typedef enum XnResolutions -{ - XN_RESOLUTION_CUSTOM = -1, - XN_RESOLUTION_QVGA = 0, // 320x240 - XN_RESOLUTION_VGA = 1, // 640x480 - XN_RESOLUTION_SXGA = 2, // 1280x1024 - XN_RESOLUTION_UXGA = 3, // 1600x1200 - - XN_RESOLUTION_COUNT, -} XnResolutions; - -typedef enum -{ - XN_SENSOR_FW_VER_UNKNOWN = 0, - XN_SENSOR_FW_VER_0_17 = 1, - XN_SENSOR_FW_VER_1_1 = 2, - XN_SENSOR_FW_VER_1_2 = 3, - XN_SENSOR_FW_VER_3_0 = 4, - XN_SENSOR_FW_VER_4_0 = 5, - XN_SENSOR_FW_VER_5_0 = 6, - XN_SENSOR_FW_VER_5_1 = 7, - XN_SENSOR_FW_VER_5_2 = 8, - XN_SENSOR_FW_VER_5_3 = 9, -} XnFWVer; - -typedef enum -{ - XN_MODE_PS = 0, - XN_MODE_MAINTENANCE = 1, - XN_MODE_SAFE_MODE = 2, -} XnParamCurrentMode; - -typedef enum { - XN_SENSOR_VER_UNKNOWN = 0, - XN_SENSOR_VER_2_0 = 1, - XN_SENSOR_VER_3_0 = 2, - XN_SENSOR_VER_4_0 = 3, - XN_SENSOR_VER_5_0 = 4 -} XnSensorVer; - -typedef enum { - XN_SENSOR_HW_VER_UNKNOWN = 0, - XN_SENSOR_HW_VER_FPDB_10 = 1, - XN_SENSOR_HW_VER_CDB_10 = 2, - XN_SENSOR_HW_VER_RD_3 = 3, - XN_SENSOR_HW_VER_RD_5 = 4 -} XnHWVer; - -typedef enum { - XN_SENSOR_CHIP_VER_UNKNOWN = 0, - XN_SENSOR_CHIP_VER_PS1000 = 1, - XN_SENSOR_CHIP_VER_PS1080 = 2 -} XnChipVer; - -typedef enum -{ - XN_CMOS_TYPE_IMAGE = 0, - XN_CMOS_TYPE_DEPTH = 1, - - XN_CMOS_COUNT -} XnCMOSType; - -typedef enum -{ - XN_IO_IMAGE_FORMAT_BAYER = 0, - XN_IO_IMAGE_FORMAT_YUV422 = 1, - XN_IO_IMAGE_FORMAT_JPEG = 2, - XN_IO_IMAGE_FORMAT_JPEG_420 = 3, - XN_IO_IMAGE_FORMAT_JPEG_MONO = 4, - XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422 = 5, - XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER = 6, -} XnIOImageFormats; - -typedef enum -{ - XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT = 0, - XN_IO_DEPTH_FORMAT_COMPRESSED_PS = 1, - XN_IO_DEPTH_FORMAT_UNCOMPRESSED_10_BIT = 2, - XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT = 3, - XN_IO_DEPTH_FORMAT_UNCOMPRESSED_12_BIT = 4, -} XnIODepthFormats; - -typedef enum -{ - XN_VIDEO_STREAM_OFF = 0, - XN_VIDEO_STREAM_COLOR = 1, - XN_VIDEO_STREAM_DEPTH = 2, - XN_VIDEO_STREAM_IR = 3, -} XnVideoStreamMode; - -typedef enum -{ - XN_AUDIO_STREAM_OFF = 0, - XN_AUDIO_STREAM_ON = 1, -} XnAudioStreamMode; - -typedef enum -{ - XN_RESET_TYPE_POWER = 0, - XN_RESET_TYPE_SOFT = 1, - XN_RESET_TYPE_SOFT_FIRST = 2, -} XnParamResetType; - -typedef enum XnSensorUsbInterface -{ - XN_SENSOR_USB_INTERFACE_DEFAULT = 0, - XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS = 1, - XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS = 2, -} XnSensorUsbInterface; - -typedef enum XnProcessingType -{ - XN_PROCESSING_DONT_CARE = 0, - XN_PROCESSING_HARDWARE = 1, - XN_PROCESSING_SOFTWARE = 2, -} XnProcessingType; - - -//--------------------------------------------------------------------------- -// Data Structures - structures that are arguments to properties -//--------------------------------------------------------------------------- - -#pragma pack (push, 1) - -typedef struct XnSDKVersion -{ - XnUInt8 nMajor; - XnUInt8 nMinor; - XnUInt8 nMaintenance; - XnUInt16 nBuild; -} XnSDKVersion; - -typedef struct { - XnUInt8 nMajor; - XnUInt8 nMinor; - XnUInt16 nBuild; - XnUInt32 nChip; - XnUInt16 nFPGA; - XnUInt16 nSystemVersion; - - XnSDKVersion SDK; - - XnHWVer HWVer; - XnFWVer FWVer; - XnSensorVer SensorVer; - XnChipVer ChipVer; -} XnVersions; - -typedef struct -{ - XnUInt16 nParam; - XnUInt16 nValue; -} XnInnerParamData; - -typedef struct XnCmosBlankingTime -{ - XnCMOSType nCmosID; - XnFloat nTimeInMilliseconds; - XnUInt16 nNumberOfFrames; -} XnCmosBlankingTime; - -typedef struct XnCmosBlankingUnits -{ - XnCMOSType nCmosID; - XnUInt16 nUnits; - XnUInt16 nNumberOfFrames; -} XnCmosBlankingUnits; - -typedef struct XnDepthAGCBin -{ - XnUInt16 nBin; - XnUInt16 nMin; - XnUInt16 nMax; -} XnDepthAGCBin; - -typedef struct XnDynamicSizeBuffer -{ - void* pData; - XnUInt32 nMaxSize; - XnUInt32 nDataSize; -} XnDynamicSizeBuffer; - - -#pragma pack (pop) - -#endif // _XN_STREAM_PARAMS_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_STREAM_PARAMS_H_ +#define _XN_STREAM_PARAMS_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +/** The maximum permitted Xiron device name string length. */ +#define XN_DEVICE_MAX_STRING_LENGTH 200 + +//--------------------------------------------------------------------------- +// Modules Names +//--------------------------------------------------------------------------- +#define XN_MODULE_NAME_DEVICE "Device" + +#define XN_MODULE_NAME_FIXED_PARAMS "FixedParams" +#define XN_MODULE_NAME_SHIFTS "Shifts" + +#ifndef XN_USE_DEVICE_3_6 +#pragma deprecated ("XN_MODULE_NAME_FIXED_PARAMS", "XN_MODULE_NAME_SHIFTS") +#endif + +//--------------------------------------------------------------------------- +// Streams Types +//--------------------------------------------------------------------------- +#define XN_STREAM_TYPE_DEPTH "Depth" +#define XN_STREAM_TYPE_IMAGE "Image" +#define XN_STREAM_TYPE_IR "IR" +#define XN_STREAM_TYPE_AUDIO "Audio" + +//--------------------------------------------------------------------------- +// Streams Names +//--------------------------------------------------------------------------- +#define XN_STREAM_NAME_DEPTH XN_STREAM_TYPE_DEPTH +#define XN_STREAM_NAME_IMAGE XN_STREAM_TYPE_IMAGE +#define XN_STREAM_NAME_IR XN_STREAM_TYPE_IR +#define XN_STREAM_NAME_AUDIO XN_STREAM_TYPE_AUDIO + +//--------------------------------------------------------------------------- +// General Properties +//--------------------------------------------------------------------------- +#define XN_STREAM_PROPERTY_TYPE "Type" +#define XN_STREAM_PROPERTY_IS_STREAM "IsStream" +#define XN_STREAM_PROPERTY_IS_FRAME_BASED "IsFrameBased" +#define XN_STREAM_PROPERTY_IS_PIXEL_BASED "IsPixelBased" +#define XN_STREAM_PROPERTY_IS_STREAMING "IsStreaming" + +/** Integer */ +#define XN_MODULE_PROPERTY_LOCK "Lock" + +//--------------------------------------------------------------------------- +// General Stream Properties +//--------------------------------------------------------------------------- +/** Integer */ +#define XN_STREAM_PROPERTY_STATE "State" +/** Integer */ +#define XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE "RequiredDataSize" +/** Integer */ +#define XN_STREAM_PROPERTY_FRAME_ID "FrameId" +/** Integer */ +#define XN_STREAM_PROPERTY_TIMESTAMP "Timestamp" +/** Integer */ +#define XN_STREAM_PROPERTY_IS_NEW_DATA "IsNew" +/** Integer (XnOutputFormats)*/ +#define XN_STREAM_PROPERTY_OUTPUT_FORMAT "OutputFormat" +/** General (void*) */ +#define XN_STREAM_PROPERTY_BUFFER "Buffer" +/** Integer */ +#define XN_STREAM_PROPERTY_BUFFER_SIZE "BufferSize" +/** Integer */ +#define XN_STREAM_PROPERTY_COMPRESSION "Compression" +/** String */ +#define XN_STREAM_PROPERTY_SHARED_BUFFER_NAME "SharedBufferName" +/** Boolean */ +#define XN_STREAM_PROPERTY_ACTUAL_READ_DATA "ActualReadData" + +/** Integer */ +#define XN_STREAM_PROPERTY_BUFFER_ALLOCATED_SIZE XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE + +#ifndef USE_DEVICE_3_6 +#pragma deprecated ("XN_STREAM_PROPERTY_BUFFER_ALLOCATED_SIZE") +#endif + +//--------------------------------------------------------------------------- +// Frame-Based Stream Properties (Depth, Image, IR) +//--------------------------------------------------------------------------- +/** Integer */ +#define XN_STREAM_PROPERTY_FPS "FPS" +/** Integer */ +#define XN_STREAM_PROPERTY_NUMBER_OF_FRAMES "NumberOfFrames" +/** Integer */ +#define XN_STREAM_PROPERTY_INPUT_FORMAT "InputFormat" +/** XnDynamicSizeBuffer */ +#define XN_STREAM_PROPERTY_LAST_RAW_FRAME "LastRawFrame" + +//--------------------------------------------------------------------------- +// Pixel-Based Stream Properties (Depth, Image, IR) +//--------------------------------------------------------------------------- +/** XnResolutions */ +#define XN_STREAM_PROPERTY_RESOLUTION "Resolution" +/** Integer */ +#define XN_STREAM_PROPERTY_X_RES "XRes" +/** Integer */ +#define XN_STREAM_PROPERTY_Y_RES "YRes" +/** Integer */ +#define XN_STREAM_PROPERTY_BYTES_PER_PIXEL "BytesPerPixel" +/** XnCropping */ +#define XN_STREAM_PROPERTY_CROPPING "Cropping" + +//--------------------------------------------------------------------------- +// Depth Specific Properties +//--------------------------------------------------------------------------- +/** Integer */ +#define XN_STREAM_PROPERTY_GAIN "Gain" +/** Integer */ +#define XN_STREAM_PROPERTY_HOLE_FILTER "HoleFilter" +/** Integer */ +#define XN_STREAM_PROPERTY_MIN_DEPTH "MinDepthValue" +/** Integer */ +#define XN_STREAM_PROPERTY_MAX_DEPTH "MaxDepthValue" +/** Integer */ +#define XN_STREAM_PROPERTY_SHADOW "ShadowValue" +/** Integer */ +#define XN_STREAM_PROPERTY_NO_SAMPLE "NoSampleValue" +/** Boolean */ +#define XN_STREAM_PROPERTY_REGISTRATION "Registration" +/** XnProcessingType */ +#define XN_STREAM_PROPERTY_REGISTRATION_TYPE "RegistrationType" +/** Boolean */ +#define XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED "WhiteBalancedEnabled" +/** XnDepthAGCBin* */ +#define XN_STREAM_PROPERTY_AGC_BIN "AGCBin" +/** Integer */ +#define XN_STREAM_PROPERTY_CONST_SHIFT "ConstShift" +/** Integer */ +#define XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR "PixelSizeFactor" +/** Integer */ +#define XN_STREAM_PROPERTY_MAX_SHIFT "MaxShift" +/** Integer */ +#define XN_STREAM_PROPERTY_PARAM_COEFF "ParamCoeff" +/** Integer */ +#define XN_STREAM_PROPERTY_SHIFT_SCALE "ShiftScale" +/** XN_DEPTH_TYPE[] */ +#define XN_STREAM_PROPERTY_S2D_TABLE "S2D" +/** XnUInt16[] */ +#define XN_STREAM_PROPERTY_D2S_TABLE "D2S" +/** Integer */ +#define XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH "DeviceMaxDepth" +/** XN_DEPTH_TYPE */ +#define XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE "ZPD" +/** Real */ +#define XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE "ZPPS" +/** Real */ +#define XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE "LDDIS" +/** Boolean */ +#define XN_STREAM_PROPERTY_GMC_MODE "GmcMode" + +//--------------------------------------------------------------------------- +// Shifts Properties (up to v3.6) +//--------------------------------------------------------------------------- +/** Integer */ +#define XN_MODULE_PROPERTY_CONST_SHIFT XN_STREAM_PROPERTY_CONST_SHIFT +/** Integer */ +#define XN_MODULE_PROPERTY_PIXEL_SIZE_FACTOR XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR +/** Integer */ +#define XN_MODULE_PROPERTY_MAX_SHIFT XN_STREAM_PROPERTY_MAX_SHIFT +/** Integer */ +#define XN_MODULE_PROPERTY_PARAM_COEFF XN_STREAM_PROPERTY_PARAM_COEFF +/** Integer */ +#define XN_MODULE_PROPERTY_SHIFT_SCALE XN_STREAM_PROPERTY_SHIFT_SCALE +/** XN_DEPTH_TYPE[] */ +#define XN_MODULE_PROPERTY_S2D_TABLE XN_STREAM_PROPERTY_S2D_TABLE +/** XnUInt16[] */ +#define XN_MODULE_PROPERTY_D2S_TABLE XN_STREAM_PROPERTY_D2S_TABLE + +#ifndef XN_USE_DEVICE_3_6 +#pragma deprecated ("XN_MODULE_PROPERTY_CONST_SHIFT", "XN_MODULE_PROPERTY_PIXEL_SIZE_FACTOR", "XN_MODULE_PROPERTY_MAX_SHIFT") +#pragma deprecated ("XN_MODULE_PROPERTY_PARAM_COEFF", "XN_MODULE_PROPERTY_SHIFT_SCALE") +#pragma deprecated ("XN_MODULE_PROPERTY_S2D_TABLE", "XN_MODULE_PROPERTY_D2S_TABLE") +#endif + +//--------------------------------------------------------------------------- +// FixedParams Properties (up to v3.6) +//--------------------------------------------------------------------------- +/** XN_DEPTH_TYPE */ +#define XN_MODULE_PROPERTY_ZERO_PLANE_DISTANCE XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE +/** Real */ +#define XN_MODULE_PROPERTY_ZERO_PLANE_PIXEL_SIZE XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE +/** Real */ +#define XN_MODULE_PROPERTY_EMITTER_DCMOS_DISTANCE XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE + +#ifndef XN_USE_DEVICE_3_6 +#pragma deprecated ("XN_MODULE_PROPERTY_ZERO_PLANE_DISTANCE", "XN_MODULE_PROPERTY_ZERO_PLANE_PIXEL_SIZE", "XN_MODULE_PROPERTY_EMITTER_DCMOS_DISTANCE") +#endif + +//--------------------------------------------------------------------------- +// Image Specific Properties +//--------------------------------------------------------------------------- +/** Integer */ +#define XN_STREAM_PROPERTY_FLICKER "Flicker" +/** Integer */ +#define XN_STREAM_PROPERTY_QUALITY "Quality" + +//--------------------------------------------------------------------------- +// Audio Specific Properties +//--------------------------------------------------------------------------- +/** XnSampleRate */ +#define XN_STREAM_PROPERTY_SAMPLE_RATE "SampleRate" +/** Integer */ +#define XN_STREAM_PROPERTY_LEFT_CHANNEL_VOLUME "LeftChannelVolume" +/** Integer */ +#define XN_STREAM_PROPERTY_RIGHT_CHANNEL_VOLUME "RightChannelVolume" +/** Integer */ +#define XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS "NumOfChannels" +/** Boolean */ +#define XN_STREAM_PROPERTY_IS_STEREO "IsStereo" +/** Integer */ +#define XN_STREAM_PROPERTY_READ_MODE "ReadMode" +/** Integer */ +#define XN_STREAM_PROPERTY_READ_CHUNK_SIZE "ReadChunkSize" +/** Integer */ +#define XN_STREAM_PROPERTY_READ_SYNC "AudioReadSync" + +#ifndef XN_USE_DEVICE_3_6 +#pragma deprecated ("XN_STREAM_PROPERTY_READ_MODE", "XN_STREAM_PROPERTY_READ_SYNC") +#endif + +//--------------------------------------------------------------------------- +// DeviceParams Properties +//--------------------------------------------------------------------------- +/** XnSDKVersion */ +#define XN_MODULE_PROPERTY_SDK_VERSION "SDKVersion" +/** String */ +#define XN_MODULE_PROPERTY_DEVICE_NAME "DeviceName" +/** String */ +#define XN_MODULE_PROPERTY_USB_PATH "USBPath" +/** Integer (XnSensorUsbInterface) */ +#define XN_MODULE_PROPERTY_USB_INTERFACE "UsbInterface" +/** Integer */ +#define XN_MODULE_PROPERTY_NUMBER_OF_BUFFERS "NumberOfBuffers" +/** Boolean */ +#define XN_MODULE_PROPERTY_READ_ENDPOINT_1 "ReadEndpoint1" +/** Boolean */ +#define XN_MODULE_PROPERTY_READ_ENDPOINT_2 "ReadEndpoint2" +/** Boolean */ +#define XN_MODULE_PROPERTY_READ_ENDPOINT_3 "ReadEndpoint3" +/** Boolean */ +#define XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP "ResetSensorOnStartup" +/** String */ +#define XN_MODULE_PROPERTY_ID "ID" +/** String */ +#define XN_MODULE_PROPERTY_PRIMARY_STREAM "PrimaryStream" +/** Boolean */ +#define XN_MODULE_PROPERTY_MIRROR "Mirror" +/** Boolean */ +#define XN_MODULE_PROPERTY_READ_DATA "ReadData" +/** Integer */ +#define XN_MODULE_PROPERTY_READ_WRITE_MODE "ReadWriteMode" +/** Integer */ +#define XN_MODULE_PROPERTY_SHARE_MODE "ShareMode" +/** Boolean */ +#define XN_MODULE_PROPERTY_FRAME_DELAY "FrameDelay" +/** Boolean */ +#define XN_MODULE_PROPERTY_FRAME_SYNC "FrameSync" +/** XnCmosBlankingUnits */ +#define XN_MODULE_PROPERTY_CMOS_BLANKING_UNITS "CmosBlankingUnits" +/** XnCmosBlankingTime */ +#define XN_MODULE_PROPERTY_CMOS_BLANKING_TIME "CmosBlankingTime" +/** XnInnerParam */ +#define XN_MODULE_PROPERTY_FIRMWARE_PARAM "FirmwareParam" +/** XnVersions */ +#define XN_MODULE_PROPERTY_VERSION "Version" +/* XnDynamicSizeBuffer */ +#define XN_MODULE_PROPERTY_FIXED_PARAMS "FixedParams" +/** Integer */ +#define XN_MODULE_PROPERTY_RESET "Reset" +/** Integer */ +#define XN_MODULE_PROPERTY_FIRMWARE_MODE "FirmwareMode" +/** Boolean */ +#define XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS "HighResTimestamps" +/** Boolean */ +#define XN_MODULE_PROPERTY_CLOSE_STREAMS_ON_SHUTDOWN "CloseStreamsOnShutdown" +/** Integer */ +#define XN_MODULE_PROPERTY_SERVER_NO_CLIENTS_TIMEOUT "ServerNoClientsTimeout" +/** Integer */ +#define XN_MODULE_PROPERTY_SERVER_START_NEW_LOG_FILE "ServerStartNewLogFile" +/** Integer */ +#define XN_MODULE_PROPERTY_ERROR_STATE "ErrorState" +/** Boolean */ +#define XN_MODULE_PROPERTY_ENABLE_MULTI_PROCESS "EnableMultiProcess" + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_PRIMARY_STREAM_ANY "Any" +#define XN_PRIMARY_STREAM_NONE "None" + +#define XN_MAX_LOG_SIZE (6*1024) + +#define XN_GAIN_AUTO 0U + +#define XN_QVGA_X_RES 320 +#define XN_QVGA_Y_RES 240 +#define XN_VGA_X_RES 640 +#define XN_VGA_Y_RES 480 +#define XN_SXGA_X_RES 1280 +#define XN_SXGA_Y_RES 1024 +#define XN_UXGA_X_RES 1600 +#define XN_UXGA_Y_RES 1200 + + +//--------------------------------------------------------------------------- +// Enums - values of various properties +//--------------------------------------------------------------------------- +typedef enum XnResolutions +{ + XN_RESOLUTION_CUSTOM = -1, + XN_RESOLUTION_QVGA = 0, // 320x240 + XN_RESOLUTION_VGA = 1, // 640x480 + XN_RESOLUTION_SXGA = 2, // 1280x1024 + XN_RESOLUTION_UXGA = 3, // 1600x1200 + + XN_RESOLUTION_COUNT, +} XnResolutions; + +typedef enum +{ + XN_SENSOR_FW_VER_UNKNOWN = 0, + XN_SENSOR_FW_VER_0_17 = 1, + XN_SENSOR_FW_VER_1_1 = 2, + XN_SENSOR_FW_VER_1_2 = 3, + XN_SENSOR_FW_VER_3_0 = 4, + XN_SENSOR_FW_VER_4_0 = 5, + XN_SENSOR_FW_VER_5_0 = 6, + XN_SENSOR_FW_VER_5_1 = 7, + XN_SENSOR_FW_VER_5_2 = 8, + XN_SENSOR_FW_VER_5_3 = 9, +} XnFWVer; + +typedef enum +{ + XN_MODE_PS = 0, + XN_MODE_MAINTENANCE = 1, + XN_MODE_SAFE_MODE = 2, +} XnParamCurrentMode; + +typedef enum { + XN_SENSOR_VER_UNKNOWN = 0, + XN_SENSOR_VER_2_0 = 1, + XN_SENSOR_VER_3_0 = 2, + XN_SENSOR_VER_4_0 = 3, + XN_SENSOR_VER_5_0 = 4 +} XnSensorVer; + +typedef enum { + XN_SENSOR_HW_VER_UNKNOWN = 0, + XN_SENSOR_HW_VER_FPDB_10 = 1, + XN_SENSOR_HW_VER_CDB_10 = 2, + XN_SENSOR_HW_VER_RD_3 = 3, + XN_SENSOR_HW_VER_RD_5 = 4 +} XnHWVer; + +typedef enum { + XN_SENSOR_CHIP_VER_UNKNOWN = 0, + XN_SENSOR_CHIP_VER_PS1000 = 1, + XN_SENSOR_CHIP_VER_PS1080 = 2 +} XnChipVer; + +typedef enum +{ + XN_CMOS_TYPE_IMAGE = 0, + XN_CMOS_TYPE_DEPTH = 1, + + XN_CMOS_COUNT +} XnCMOSType; + +typedef enum +{ + XN_IO_IMAGE_FORMAT_BAYER = 0, + XN_IO_IMAGE_FORMAT_YUV422 = 1, + XN_IO_IMAGE_FORMAT_JPEG = 2, + XN_IO_IMAGE_FORMAT_JPEG_420 = 3, + XN_IO_IMAGE_FORMAT_JPEG_MONO = 4, + XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422 = 5, + XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER = 6, +} XnIOImageFormats; + +typedef enum +{ + XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT = 0, + XN_IO_DEPTH_FORMAT_COMPRESSED_PS = 1, + XN_IO_DEPTH_FORMAT_UNCOMPRESSED_10_BIT = 2, + XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT = 3, + XN_IO_DEPTH_FORMAT_UNCOMPRESSED_12_BIT = 4, +} XnIODepthFormats; + +typedef enum +{ + XN_VIDEO_STREAM_OFF = 0, + XN_VIDEO_STREAM_COLOR = 1, + XN_VIDEO_STREAM_DEPTH = 2, + XN_VIDEO_STREAM_IR = 3, +} XnVideoStreamMode; + +typedef enum +{ + XN_AUDIO_STREAM_OFF = 0, + XN_AUDIO_STREAM_ON = 1, +} XnAudioStreamMode; + +typedef enum +{ + XN_RESET_TYPE_POWER = 0, + XN_RESET_TYPE_SOFT = 1, + XN_RESET_TYPE_SOFT_FIRST = 2, +} XnParamResetType; + +typedef enum XnSensorUsbInterface +{ + XN_SENSOR_USB_INTERFACE_DEFAULT = 0, + XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS = 1, + XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS = 2, +} XnSensorUsbInterface; + +typedef enum XnProcessingType +{ + XN_PROCESSING_DONT_CARE = 0, + XN_PROCESSING_HARDWARE = 1, + XN_PROCESSING_SOFTWARE = 2, +} XnProcessingType; + + +//--------------------------------------------------------------------------- +// Data Structures - structures that are arguments to properties +//--------------------------------------------------------------------------- + +#pragma pack (push, 1) + +typedef struct XnSDKVersion +{ + XnUInt8 nMajor; + XnUInt8 nMinor; + XnUInt8 nMaintenance; + XnUInt16 nBuild; +} XnSDKVersion; + +typedef struct { + XnUInt8 nMajor; + XnUInt8 nMinor; + XnUInt16 nBuild; + XnUInt32 nChip; + XnUInt16 nFPGA; + XnUInt16 nSystemVersion; + + XnSDKVersion SDK; + + XnHWVer HWVer; + XnFWVer FWVer; + XnSensorVer SensorVer; + XnChipVer ChipVer; +} XnVersions; + +typedef struct +{ + XnUInt16 nParam; + XnUInt16 nValue; +} XnInnerParamData; + +typedef struct XnCmosBlankingTime +{ + XnCMOSType nCmosID; + XnFloat nTimeInMilliseconds; + XnUInt16 nNumberOfFrames; +} XnCmosBlankingTime; + +typedef struct XnCmosBlankingUnits +{ + XnCMOSType nCmosID; + XnUInt16 nUnits; + XnUInt16 nNumberOfFrames; +} XnCmosBlankingUnits; + +typedef struct XnDepthAGCBin +{ + XnUInt16 nBin; + XnUInt16 nMin; + XnUInt16 nMax; +} XnDepthAGCBin; + +typedef struct XnDynamicSizeBuffer +{ + void* pData; + XnUInt32 nMaxSize; + XnUInt32 nDataSize; +} XnDynamicSizeBuffer; + + +#pragma pack (pop) + +#endif // _XN_STREAM_PARAMS_H_ diff --git a/LGPL.txt b/LGPL.txt index b14ca0a..65c5ca8 100644 --- a/LGPL.txt +++ b/LGPL.txt @@ -1,165 +1,165 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/NITE/Data/Sample-Scene.xml b/NITE/Data/Sample-Scene.xml index f131fa0..211936b 100644 --- a/NITE/Data/Sample-Scene.xml +++ b/NITE/Data/Sample-Scene.xml @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NITE/Data/Sample-Tracking.xml b/NITE/Data/Sample-Tracking.xml index 59628e5..a3d91d3 100644 --- a/NITE/Data/Sample-Tracking.xml +++ b/NITE/Data/Sample-Tracking.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NITE/Data/Sample-User.xml b/NITE/Data/Sample-User.xml index fad8b1d..eeb7ebd 100644 --- a/NITE/Data/Sample-User.xml +++ b/NITE/Data/Sample-User.xml @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenNI/Data/SamplesConfig.xml b/OpenNI/Data/SamplesConfig.xml index a2b7adf..2726cdf 100644 --- a/OpenNI/Data/SamplesConfig.xml +++ b/OpenNI/Data/SamplesConfig.xml @@ -1,66 +1,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Linux-x86/Build/Makefile b/Platform/Linux-x86/Build/Makefile index d482819..f111c7b 100644 --- a/Platform/Linux-x86/Build/Makefile +++ b/Platform/Linux-x86/Build/Makefile @@ -1,76 +1,76 @@ - -#/****************************************************************************** -#* * -#* PrimeSense Sensor 5.0 Makefile * -#* Copyright (C) 2010 PrimeSense Ltd. * -#* * -#******************************************************************************/ -# default config is Release -ifndef CFG - CFG = Release -endif - -# list all modules -ALL_PROJS = \ - XnCore \ - XnFormats \ - XnDDK \ - XnDeviceSensorV2 \ - Utils/XnSensorServer \ - XnDeviceFile \ - - -ALL_PROJS_CLEAN = $(foreach proj,$(ALL_PROJS),$(proj)-clean) - -# define a function which creates a target for each proj -define CREATE_PROJ_TARGET - -.PHONY: $1 $1-clean - -$1: - $(MAKE) -C $1 CFG=$(CFG) - -$1-clean: - $(MAKE) -C $1 CFG=$(CFG) clean - -endef - -########### TARGETS ############## - -.PHONY: all install uninstall clean - -# make all makefiles -all: $(ALL_PROJS) - -# create projects targets -$(foreach proj,$(ALL_PROJS),$(eval $(call CREATE_PROJ_TARGET,$(proj)))) - -# additional dependencies -XnFormats: XnCore -XnDDK: XnCore -XnDDK: XnFormats -XnLeanDeviceSensorV2: XnDDK -XnLeanDeviceSensorV2: XnFormats -XnLeanDeviceSensorV2: XnCore -Utils/XnSensorServer: XnDDK -Utils/XnSensorServer: XnDeviceSensorV2 -Utils/XnSensorServer: XnFormats -XnDeviceFile: XnCore -XnDeviceFile: XnDDK -XnDeviceFile: XnFormats - -# clean is cleaning all projects -clean: $(ALL_PROJS_CLEAN) - -# redist target -redist: all - cd ../CreateRedist; ./RedistMaker; cd - - -# install target -install: redist - cd ../Redist; ./install.sh; cd - - -# uninstall -uninstall: - cd ../Redist; ./install.sh -u; cd - - + +#/****************************************************************************** +#* * +#* PrimeSense Sensor 5.0 Makefile * +#* Copyright (C) 2010 PrimeSense Ltd. * +#* * +#******************************************************************************/ +# default config is Release +ifndef CFG + CFG = Release +endif + +# list all modules +ALL_PROJS = \ + XnCore \ + XnFormats \ + XnDDK \ + XnDeviceSensorV2 \ + Utils/XnSensorServer \ + XnDeviceFile \ + + +ALL_PROJS_CLEAN = $(foreach proj,$(ALL_PROJS),$(proj)-clean) + +# define a function which creates a target for each proj +define CREATE_PROJ_TARGET + +.PHONY: $1 $1-clean + +$1: + $(MAKE) -C $1 CFG=$(CFG) + +$1-clean: + $(MAKE) -C $1 CFG=$(CFG) clean + +endef + +########### TARGETS ############## + +.PHONY: all install uninstall clean + +# make all makefiles +all: $(ALL_PROJS) + +# create projects targets +$(foreach proj,$(ALL_PROJS),$(eval $(call CREATE_PROJ_TARGET,$(proj)))) + +# additional dependencies +XnFormats: XnCore +XnDDK: XnCore +XnDDK: XnFormats +XnLeanDeviceSensorV2: XnDDK +XnLeanDeviceSensorV2: XnFormats +XnLeanDeviceSensorV2: XnCore +Utils/XnSensorServer: XnDDK +Utils/XnSensorServer: XnDeviceSensorV2 +Utils/XnSensorServer: XnFormats +XnDeviceFile: XnCore +XnDeviceFile: XnDDK +XnDeviceFile: XnFormats + +# clean is cleaning all projects +clean: $(ALL_PROJS_CLEAN) + +# redist target +redist: all + cd ../CreateRedist; ./RedistMaker; cd - + +# install target +install: redist + cd ../Redist; ./install.sh; cd - + +# uninstall +uninstall: + cd ../Redist; ./install.sh -u; cd - + diff --git a/Platform/Linux-x86/Build/XnFormats/Makefile b/Platform/Linux-x86/Build/XnFormats/Makefile index 5f19943..4a04486 100644 --- a/Platform/Linux-x86/Build/XnFormats/Makefile +++ b/Platform/Linux-x86/Build/XnFormats/Makefile @@ -3,7 +3,7 @@ SRC_FILES = \ ../../../../Source/External/LibJPEG/*.c LIB_NAME = XnFormats -LIB_USED = XnCore OpenNI +USED_LIBS = XnCore OpenNI DEFINES = XN_FORMATS_EXPORTS INC_DIRS = ../../../../Source/External/LibJPEG diff --git a/Platform/Linux-x86/CreateRedist/RedistMaker b/Platform/Linux-x86/CreateRedist/RedistMaker index c500be2..f0d6d70 100755 --- a/Platform/Linux-x86/CreateRedist/RedistMaker +++ b/Platform/Linux-x86/CreateRedist/RedistMaker @@ -3,10 +3,11 @@ SCRIPT_DIR=`pwd` # Take version -MAJOR=`grep "#define XN_PS_MAJOR_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }'` -MINOR=`grep "#define XN_PS_MINOR_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }'` -MAINTENANCE=`grep "#define XN_PS_MAINTENANCE_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }'` -BUILD=`grep "#define XN_PS_BUILD_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }'` +MAJOR=`grep "#define XN_PS_MAJOR_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }' | strings -n 1` +MINOR=`grep "#define XN_PS_MINOR_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }' | strings -n 1` +MAINTENANCE=`grep "#define XN_PS_MAINTENANCE_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }' | strings -n 1` +BUILD=`grep "#define XN_PS_BUILD_VERSION" ../../../Include/XnPsVersion.h | awk '{ print $3 }' | strings -n 1` + PS_VERSION="$MAJOR.$MINOR.$MAINTENANCE.$BUILD" @@ -27,11 +28,11 @@ mkdir -p ../Redist/Config # copy files to redist cp ../../../GPL.txt ../Redist cp ../../../LGPL.txt ../Redist -cp ../Bin/Release/libXnDeviceSensorV2.so ../Redist/Lib -cp ../Bin/Release/libXnDeviceFile.so ../Redist/Lib -cp ../Bin/Release/libXnDDK.so ../Redist/Lib -cp ../Bin/Release/libXnFormats.so ../Redist/Lib -cp ../Bin/Release/libXnCore.so ../Redist/Lib +cp ../Bin/Release/libXnDeviceSensorV2.* ../Redist/Lib +cp ../Bin/Release/libXnDeviceFile.* ../Redist/Lib +cp ../Bin/Release/libXnDDK.* ../Redist/Lib +cp ../Bin/Release/libXnFormats.* ../Redist/Lib +cp ../Bin/Release/libXnCore.* ../Redist/Lib cp ../Bin/Release/XnSensorServer ../Redist/Bin cp ../Install/* ../Redist/Install cp ../../../Data/GlobalDefaults.ini ../Redist/Config @@ -40,7 +41,18 @@ cp install.sh ../Redist # create tar mkdir -p Final cd ../Redist -tar -cjf $SCRIPT_DIR/Final/Engine.v$PS_VERSION.tar.bz2 * -cd - +if [ "`uname -s`" == "Darwin" ]; then + TAR_TARGET="MacOSX" +elif [ "`uname -m`" == "i686" ]; then + TAR_TARGET="Linux32" +elif [ "`uname -m`" == "x86_64" ]; then + TAR_TARGET="Linux64" +else + TAR_TARGET="Linux" +fi + +tar -cjf $SCRIPT_DIR/Final/Sensor-Bin-$TAR_TARGET-v$PS_VERSION.tar.bz2 * + +cd - diff --git a/Platform/Linux-x86/CreateRedist/install.sh b/Platform/Linux-x86/CreateRedist/install.sh index 56a6ecd..19978f7 100755 --- a/Platform/Linux-x86/CreateRedist/install.sh +++ b/Platform/Linux-x86/CreateRedist/install.sh @@ -7,7 +7,12 @@ INSTALL_BIN=/usr/bin INSTALL_ETC=/usr/etc/primesense INSTALL_RULES=/etc/udev/rules.d -MODULES="libXnDeviceSensorV2.so libXnDeviceFile.so" +if [ "`uname -s`" == "Darwin" ]; then + MODULES="libXnDeviceSensorV2.dylib libXnDeviceFile.dylib" +else + MODULES="libXnDeviceSensorV2.so libXnDeviceFile.so" +fi + RULES_FILE="55-primesense-usb.rules" # read arguments @@ -78,10 +83,12 @@ if [ "$INSTALL" == "1" ]; then chmod a+w /var/log/primesense/XnSensorServer printf "OK\n" - # install USB rules (so that PrimeSense sensors will be mounted with write permissions) - printf "installing usb rules..." - cp Install/$RULES_FILE $INSTALL_RULES - printf "OK\n" + if [ "`uname -s`" != "Darwin" ]; then + # install USB rules (so that PrimeSense sensors will be mounted with write permissions) + printf "installing usb rules..." + cp Install/$RULES_FILE $INSTALL_RULES + printf "OK\n" + fi else #uninstall @@ -112,10 +119,12 @@ else #uninstall rm -rf $INSTALL_ETC printf "OK\n" - # remove USB rules - printf "removing usb rules..." - rm -f $INSTALL_RULES/$RULES_FILE - printf "OK\n" + if [ "`uname -s`" != "Darwin" ]; then + # remove USB rules + printf "removing usb rules..." + rm -f $INSTALL_RULES/$RULES_FILE + printf "OK\n" + fi fi diff --git a/Platform/Mac/Bin/Test/build_test.sh b/Platform/Mac/Bin/Test/build_test.sh new file mode 100755 index 0000000..0fc2d60 --- /dev/null +++ b/Platform/Mac/Bin/Test/build_test.sh @@ -0,0 +1,6 @@ +#!/bin/sh +base=${PWD} +root_dir=${base}/../../../../ +install_dir="./../../../../../OpenNI_TEST" +cmake -DCMAKE_INSTALL_PREFIX=$install_dir -DCMAKE_BUILD_TYPE:STRING=Release -DCREATE_TEST_BUILD:BOOL=ON ${root_dir} + diff --git a/Platform/Mac/Bin/Test/clean_test.sh b/Platform/Mac/Bin/Test/clean_test.sh new file mode 100755 index 0000000..f1c2ade --- /dev/null +++ b/Platform/Mac/Bin/Test/clean_test.sh @@ -0,0 +1,9 @@ +#!/bin/sh +rm *.txt +rm *.so +rm Makefile +rm -rf Source +rm -rf CMakeFiles +rm XnSensorServer +rm cmake_install.cmake +rm *.dylib diff --git a/Platform/Mac/Bin/openFrameworks/build.sh b/Platform/Mac/Bin/openFrameworks/build.sh new file mode 100755 index 0000000..fbfdc88 --- /dev/null +++ b/Platform/Mac/Bin/openFrameworks/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh +base=${PWD} +root_dir=${base}/../../../../ +install_dir="./../../../../../OpenNI_openFrameworks" +cmake -DCMAKE_INSTALL_PREFIX=$install_dir -DCMAKE_BUILD_TYPE:STRING=Release -DCREATE_TEST_BUILD:BOOL=OFF -DCREATE_OF_BUILD:BOOL=ON ${root_dir} + diff --git a/Platform/Mac/Bin/openFrameworks/clean.sh b/Platform/Mac/Bin/openFrameworks/clean.sh new file mode 100755 index 0000000..f1c2ade --- /dev/null +++ b/Platform/Mac/Bin/openFrameworks/clean.sh @@ -0,0 +1,9 @@ +#!/bin/sh +rm *.txt +rm *.so +rm Makefile +rm -rf Source +rm -rf CMakeFiles +rm XnSensorServer +rm cmake_install.cmake +rm *.dylib diff --git a/Platform/Win32/Build/Engine.sln b/Platform/Win32/Build/Engine.sln index 82db0dd..7c95201 100644 --- a/Platform/Win32/Build/Engine.sln +++ b/Platform/Win32/Build/Engine.sln @@ -1,36 +1,36 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnCore", "XnCore\XnCore.vcproj", "{7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A}" -EndProject -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnFormats", "XnFormats\XnFormats.vcproj", "{9CAEC325-EEE6-4A91-8819-004E20C419C0}" - ProjectSection(ProjectDependencies) = postProject - {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} - EndProjectSection -EndProject -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDDK", "XnDDK\XnDDK.vcproj", "{FB08A9D1-10AF-418D-8786-F58FDF11254D}" - ProjectSection(ProjectDependencies) = postProject - {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} - {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} - EndProjectSection -EndProject -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDeviceSensorV2", "XnDeviceSensorV2\XnDeviceSensorV2.vcproj", "{1653839A-ABA5-4c0e-9EA2-2640B0275894}" - ProjectSection(ProjectDependencies) = postProject - {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} - {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} - {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} - EndProjectSection -EndProject -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "Utils\XnSensorServer", "Utils\XnSensorServer\XnSensorServer.vcproj", "{F68C824E-EA49-4A3C-A233-ADE2B3ECC375}" - ProjectSection(ProjectDependencies) = postProject - {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} - {1653839A-ABA5-4c0e-9EA2-2640B0275894} = {1653839A-ABA5-4c0e-9EA2-2640B0275894} - {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} - EndProjectSection -EndProject -Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDeviceFile", "XnDeviceFile\XnDeviceFile.vcproj", "{7410A46D-8120-4C95-B7B4-BC8AFEBBBD5B}" - ProjectSection(ProjectDependencies) = postProject - {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} - {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} - {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} - EndProjectSection -EndProject +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnCore", "XnCore\XnCore.vcproj", "{7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A}" +EndProject +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnFormats", "XnFormats\XnFormats.vcproj", "{9CAEC325-EEE6-4A91-8819-004E20C419C0}" + ProjectSection(ProjectDependencies) = postProject + {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} + EndProjectSection +EndProject +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDDK", "XnDDK\XnDDK.vcproj", "{FB08A9D1-10AF-418D-8786-F58FDF11254D}" + ProjectSection(ProjectDependencies) = postProject + {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} + {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} + EndProjectSection +EndProject +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDeviceSensorV2", "XnDeviceSensorV2\XnDeviceSensorV2.vcproj", "{1653839A-ABA5-4c0e-9EA2-2640B0275894}" + ProjectSection(ProjectDependencies) = postProject + {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} + {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} + {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} + EndProjectSection +EndProject +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "Utils\XnSensorServer", "Utils\XnSensorServer\XnSensorServer.vcproj", "{F68C824E-EA49-4A3C-A233-ADE2B3ECC375}" + ProjectSection(ProjectDependencies) = postProject + {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} + {1653839A-ABA5-4c0e-9EA2-2640B0275894} = {1653839A-ABA5-4c0e-9EA2-2640B0275894} + {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} + EndProjectSection +EndProject +Project("{19091980-2008-4CFA-1491-04CC20D8BCF9}") = "XnDeviceFile", "XnDeviceFile\XnDeviceFile.vcproj", "{7410A46D-8120-4C95-B7B4-BC8AFEBBBD5B}" + ProjectSection(ProjectDependencies) = postProject + {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} = {7410A46D-8120-4C95-B7B4-BC8AFEBBBD5A} + {FB08A9D1-10AF-418D-8786-F58FDF11254D} = {FB08A9D1-10AF-418D-8786-F58FDF11254D} + {9CAEC325-EEE6-4A91-8819-004E20C419C0} = {9CAEC325-EEE6-4A91-8819-004E20C419C0} + EndProjectSection +EndProject diff --git a/Platform/Win32/Build/Res/DDK.rc b/Platform/Win32/Build/Res/DDK.rc index 19326d8..3f59b15 100644 --- a/Platform/Win32/Build/Res/DDK.rc +++ b/Platform/Win32/Build/Res/DDK.rc @@ -1,123 +1,123 @@ -// Microsoft Visual C++ generated resource script. -// -#include "Resource-DDK.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Swedish resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) -#ifdef _WIN32 -LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "Resource-DDK.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Swedish resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// Hebrew resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HEB) -#ifdef _WIN32 -LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT -#pragma code_page(1255) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_MAINICON ICON "mainicon.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION XN_PS_MAJOR_VERSION,XN_PS_MINOR_VERSION,XN_PS_MAINTENANCE_VERSION,XN_PS_BUILD_VERSION - PRODUCTVERSION XN_PS_MAJOR_VERSION,XN_PS_MINOR_VERSION,XN_PS_MAINTENANCE_VERSION,XN_PS_BUILD_VERSION - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x0L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Prime Sense Ltd." - VALUE "FileDescription", "Prime Sense Device Development Kit" - VALUE "FileVersion", XN_PS_BRIEF_VERSION_STRING - VALUE "InternalName", "PSDDK" - VALUE "LegalCopyright", "Copyright (C) 2007" - VALUE "ProductName", "Prime Sense Device Development Kit" - VALUE "ProductVersion", XN_PS_BRIEF_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // Hebrew resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +// Microsoft Visual C++ generated resource script. +// +#include "Resource-DDK.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Swedish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) +#ifdef _WIN32 +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "Resource-DDK.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Swedish resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Hebrew resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HEB) +#ifdef _WIN32 +LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT +#pragma code_page(1255) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAINICON ICON "mainicon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION XN_PS_MAJOR_VERSION,XN_PS_MINOR_VERSION,XN_PS_MAINTENANCE_VERSION,XN_PS_BUILD_VERSION + PRODUCTVERSION XN_PS_MAJOR_VERSION,XN_PS_MINOR_VERSION,XN_PS_MAINTENANCE_VERSION,XN_PS_BUILD_VERSION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000904b0" + BEGIN + VALUE "CompanyName", "Prime Sense Ltd." + VALUE "FileDescription", "Prime Sense Device Development Kit" + VALUE "FileVersion", XN_PS_BRIEF_VERSION_STRING + VALUE "InternalName", "PSDDK" + VALUE "LegalCopyright", "Copyright (C) 2007" + VALUE "ProductName", "Prime Sense Device Development Kit" + VALUE "ProductVersion", XN_PS_BRIEF_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x9, 1200 + END +END + +#endif // Hebrew resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Platform/Win32/Build/Res/Resource-DDK.h b/Platform/Win32/Build/Res/Resource-DDK.h index c1e2fbb..2ee31bd 100644 --- a/Platform/Win32/Build/Res/Resource-DDK.h +++ b/Platform/Win32/Build/Res/Resource-DDK.h @@ -1,41 +1,41 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by DDK.rc -// -#define IDI_MAINICON 110 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 116 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1016 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DDK.rc +// +#define IDI_MAINICON 110 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 116 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1016 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Platform/Win32/Build/Utils/XnSensorServer/XnSensorServer.vcproj b/Platform/Win32/Build/Utils/XnSensorServer/XnSensorServer.vcproj index f9285cd..34f2139 100644 --- a/Platform/Win32/Build/Utils/XnSensorServer/XnSensorServer.vcproj +++ b/Platform/Win32/Build/Utils/XnSensorServer/XnSensorServer.vcproj @@ -1,214 +1,214 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/Build/XnCore/XnCore.vcproj b/Platform/Win32/Build/XnCore/XnCore.vcproj index e2acb03..53eedbb 100644 --- a/Platform/Win32/Build/XnCore/XnCore.vcproj +++ b/Platform/Win32/Build/XnCore/XnCore.vcproj @@ -1,316 +1,316 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/Build/XnDDK/XnDDK.vcproj b/Platform/Win32/Build/XnDDK/XnDDK.vcproj index d2a482e..7bbef5c 100644 --- a/Platform/Win32/Build/XnDDK/XnDDK.vcproj +++ b/Platform/Win32/Build/XnDDK/XnDDK.vcproj @@ -1,659 +1,659 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/Build/XnDeviceFile/XnDeviceFile.vcproj b/Platform/Win32/Build/XnDeviceFile/XnDeviceFile.vcproj index 4953810..200252c 100644 --- a/Platform/Win32/Build/XnDeviceFile/XnDeviceFile.vcproj +++ b/Platform/Win32/Build/XnDeviceFile/XnDeviceFile.vcproj @@ -1,297 +1,297 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/Build/XnDeviceSensorV2/XnDeviceSensorV2.vcproj b/Platform/Win32/Build/XnDeviceSensorV2/XnDeviceSensorV2.vcproj index aa1ebbd..3092866 100644 --- a/Platform/Win32/Build/XnDeviceSensorV2/XnDeviceSensorV2.vcproj +++ b/Platform/Win32/Build/XnDeviceSensorV2/XnDeviceSensorV2.vcproj @@ -1,752 +1,752 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/Build/XnFormats/XnFormats.vcproj b/Platform/Win32/Build/XnFormats/XnFormats.vcproj index 52fc8a9..215b695 100644 --- a/Platform/Win32/Build/XnFormats/XnFormats.vcproj +++ b/Platform/Win32/Build/XnFormats/XnFormats.vcproj @@ -1,531 +1,531 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Win32/CreateRedist/Engine.nsi b/Platform/Win32/CreateRedist/Engine.nsi index 8dc6755..2e936b8 100644 --- a/Platform/Win32/CreateRedist/Engine.nsi +++ b/Platform/Win32/CreateRedist/Engine.nsi @@ -1,214 +1,214 @@ -;/**************************************************************************** -;* * -;* PrimeSense Sensor 5.0 Alpha * -;* Copyright (C) 2010 PrimeSense Ltd. * -;* * -;* This file is part of PrimeSense Common. * -;* * -;* PrimeSense Sensor is free software: you can redistribute it and/or modify* -;* it under the terms of the GNU Lesser General Public License as published * -;* by the Free Software Foundation, either version 3 of the License, or * -;* (at your option) any later version. * -;* * -;* PrimeSense Sensor is distributed in the hope that it will be useful, * -;* but WITHOUT ANY WARRANTY; without even the implied warranty of * -;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -;* GNU Lesser General Public License for more details. * -;* * -;* You should have received a copy of the GNU Lesser General Public License * -;* along with PrimeSense Sensor. If not, see .* -;* * -;****************************************************************************/ -; - -; - - -;SetCompress off -SetCompress auto -SetCompressor ZLIB - -!include "MUI.nsh" -!include "x64.nsh" -!include "winmessages.nsh" -!include LogicLib.nsh -!include "FileFunc.nsh" -;*************** -;*** General *** -;*************** -!define EE_VER "5.0.0" -!define EE_NAME "PrimeSensor ${EE_VER} for Windows (Kinect Mod)" -!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' -!define OPENNI_VER "1.0.0" -!define OPENNI_NAME "PrimeSense - OpenNI ${OPENNI_VER} for Windows" -Var OPEN_NI_INST - -Name "${EE_NAME}" -OutFile "Output\SensorKinect-Win32-${EE_VER}.exe" -InstallDir "$PROGRAMFILES\Prime Sense\Sensor" - -;******************************* -;*** face Configuration *** -;******************************* -!define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP "Header.bmp" -!define MUI_ABORTWARNING - -;************* -;*** Pages *** -;************* -;!insertmacro MUI_PAGE_LICENSE "License.txt" --- Not needed for now -!insertmacro MUI_PAGE_COMPONENTS -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -;**************** -;*** Languages*** -;**************** -!insertmacro MUI_LANGUAGE "English" - -;*************** -;*** Install *** -;*************** - -; OpenNI Section -Section "OpenNI" - - ; Section is mandatory - SectionIn RO - - ClearErrors - ReadRegStr $0 HKLM "Software\OpenNI" "Version" - IfErrors NotInstalled - - - ; Check the version - ${If} $0 == ${OPENNI_VER} - ; That version is already installed - ${Else} - ; Is installed with diferent version, install to the same directory - ReadEnvStr $3 "OPEN_NI_INSTALL_PATH" - ExecWait "OpenNI-Win32-${OPENNI_VER}.exe /D=$3" - ${EndIf} - - - Goto Done - - AddSize 121902 - - - NotInstalled: - ExecWait "OpenNI-Win32-${OPENNI_VER}.exe" - - Done: - -SectionEnd - - - -; EE Section -Section "Sensor" Sensor - - CreateDirectory $INSTDIR - CreateDirectory "$INSTDIR\Bin" - CreateDirectory "$INSTDIR\Data" - - ; Copy all the files from the redist dir - File "/oname=$INSTDIR\GPL.txt" ..\redist\GPL.txt - File "/oname=$INSTDIR\LGPL.txt" ..\redist\LGPL.txt - File "/oname=$INSTDIR\Bin\XnCore.dll" ..\redist\Bin\XnCore.dll - File "/oname=$INSTDIR\Bin\XnFormats.dll" ..\redist\Bin\XnFormats.dll - File "/oname=$INSTDIR\Bin\XnDDK.dll" ..\redist\Bin\XnDDK.dll - File "/oname=$INSTDIR\Bin\XnDeviceSensorV2.dll" ..\redist\Bin\XnDeviceSensorV2.dll - File "/oname=$INSTDIR\Bin\XnDeviceFile.dll" ..\redist\Bin\XnDeviceFile.dll - File "/oname=$INSTDIR\Bin\XnSensorServer.exe" ..\redist\Bin\XnSensorServer.exe - File "/oname=$INSTDIR\Data\GlobalDefaults.ini" ..\redist\Data\GlobalDefaults.ini - - SetOutPath "$INSTDIR\Driver" - File /r ..\driver\*.* - - SetOutPath "$INSTDIR\Tools" - File /r ..\tools\*.* - - SetOutPath "$INSTDIR\SampleXMLs" - File /r ..\..\..\NITE - File /r ..\..\..\OPENNI - - ; Register it in OpenNI - ReadRegStr $OPEN_NI_INST HKLM "Software\OpenNI" "InstallDir" - ; Also add OPEN_NI_INSTALL_PATH to current environment (current environment is not updated by writing to registry) - System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("OPEN_NI_INSTALL_PATH", "$OPEN_NI_INST").r2' - ExecWait '"$OPEN_NI_INST\Bin\niReg.exe" "$INSTDIR\Bin\XnDeviceFile.dll"' - IfErrors FailedToRegister - ExecWait '"$OPEN_NI_INST\Bin\niReg.exe" "$INSTDIR\Bin\XnDeviceSensorV2.dll" "$INSTDIR\Data"' - IfErrors FailedToRegister - - ; Install the visual studio 2010 DLLs - ExecWait '"$INSTDIR\Tools\vcredist_x86.exe" /q' - - ; Install the USB Driver - ${If} ${RunningX64} - ExecWait '"$INSTDIR\Driver\dpinst-amd64.exe" /sw /el' - ${Else} - ExecWait '"$INSTDIR\Driver\dpinst-x86.exe" /sw /el' - ${EndIf} - - ; Create an uninstaller - WriteUninstaller "$INSTDIR\Uninstall EE ${EE_VER}.exe" - - ; Register the .xns file type - WriteRegStr HKCR ".xns" "" "PrimeSenseRecording" - WriteRegStr HKCR "PrimeSenseRecording" "" "PrimeSense Recording File" - WriteRegStr HKCR "PrimeSenseRecording\DefaultIcon" "" "$OPEN_NI_INST\Samples\Bin\Release\NiViewer.exe,0" - WriteRegStr HKCR "PrimeSenseRecording\shell\open\command" "" '"$OPEN_NI_INST\Samples\Bin\Release\NiViewer.exe" "%1"' - - ; Add the uninstall option into the control panel add/remove - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" "DisplayName"\ - "${EE_NAME} (remove only)" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" "UninstallString" \ - "$INSTDIR\Uninstall EE ${EE_VER}.exe" - - WriteRegStr HKLM "Software\PrimeSense\EE" "Version" "${EE_VER}" - - ; Add Env Var - WriteRegExpandStr ${env_hklm} XN_EE_INSTALL_PATH $INSTDIR - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - Goto Done - - FailedToRegister: - MessageBox MB_OK|MB_ICONSTOP "Installation Failed! Could not register module with OpenNI!" - Abort "Installation Failed! Could not register module with OpenNI!" - - Done: - -SectionEnd - - -;***************** -;*** Uninstall *** -;***************** -Section "Uninstall" - ; Unreg from OpenNI - ReadEnvStr $0 "OPEN_NI_BIN" - ExecWait '"$0\niReg.exe" -u "$INSTDIR\Bin\XnDeviceFile.dll"' - ExecWait '"$0\niReg.exe" -u "$INSTDIR\Bin\XnDeviceSensorV2.dll"' - - ; Unregister the .xns file type - DeleteRegKey HKCR ".xns" - DeleteRegKey HKCR "PrimeSenseRecording" - - ; Delete the files - RMDir /r /REBOOTOK $INSTDIR - RMDir $INSTDIR - - ; Delete the uninstall option from the control panel add/remove - DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" - DeleteRegKey HKLM "Software\PrimeSense\EE" - - ; Remove the Env Var - DeleteRegValue ${env_hklm} XN_EE_INSTALL_PATH - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - +;/**************************************************************************** +;* * +;* PrimeSense Sensor 5.0 Alpha * +;* Copyright (C) 2010 PrimeSense Ltd. * +;* * +;* This file is part of PrimeSense Common. * +;* * +;* PrimeSense Sensor is free software: you can redistribute it and/or modify* +;* it under the terms of the GNU Lesser General Public License as published * +;* by the Free Software Foundation, either version 3 of the License, or * +;* (at your option) any later version. * +;* * +;* PrimeSense Sensor is distributed in the hope that it will be useful, * +;* but WITHOUT ANY WARRANTY; without even the implied warranty of * +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +;* GNU Lesser General Public License for more details. * +;* * +;* You should have received a copy of the GNU Lesser General Public License * +;* along with PrimeSense Sensor. If not, see .* +;* * +;****************************************************************************/ +; + +; + + +;SetCompress off +SetCompress auto +SetCompressor ZLIB + +!include "MUI.nsh" +!include "x64.nsh" +!include "winmessages.nsh" +!include LogicLib.nsh +!include "FileFunc.nsh" +;*************** +;*** General *** +;*************** +!define EE_VER "5.0.0" +!define EE_NAME "PrimeSensor ${EE_VER} for Windows (Kinect Mod)" +!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' +!define OPENNI_VER "1.0.0" +!define OPENNI_NAME "PrimeSense - OpenNI ${OPENNI_VER} for Windows" +Var OPEN_NI_INST + +Name "${EE_NAME}" +OutFile "Output\SensorKinect-Win32-${EE_VER}.exe" +InstallDir "$PROGRAMFILES\Prime Sense\Sensor" + +;******************************* +;*** face Configuration *** +;******************************* +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP "Header.bmp" +!define MUI_ABORTWARNING + +;************* +;*** Pages *** +;************* +;!insertmacro MUI_PAGE_LICENSE "License.txt" --- Not needed for now +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +;**************** +;*** Languages*** +;**************** +!insertmacro MUI_LANGUAGE "English" + +;*************** +;*** Install *** +;*************** + +; OpenNI Section +Section "OpenNI" + + ; Section is mandatory + SectionIn RO + + ClearErrors + ReadRegStr $0 HKLM "Software\OpenNI" "Version" + IfErrors NotInstalled + + + ; Check the version + ${If} $0 == ${OPENNI_VER} + ; That version is already installed + ${Else} + ; Is installed with diferent version, install to the same directory + ReadEnvStr $3 "OPEN_NI_INSTALL_PATH" + ExecWait "OpenNI-Win32-${OPENNI_VER}.exe /D=$3" + ${EndIf} + + + Goto Done + + AddSize 121902 + + + NotInstalled: + ExecWait "OpenNI-Win32-${OPENNI_VER}.exe" + + Done: + +SectionEnd + + + +; EE Section +Section "Sensor" Sensor + + CreateDirectory $INSTDIR + CreateDirectory "$INSTDIR\Bin" + CreateDirectory "$INSTDIR\Data" + + ; Copy all the files from the redist dir + File "/oname=$INSTDIR\GPL.txt" ..\redist\GPL.txt + File "/oname=$INSTDIR\LGPL.txt" ..\redist\LGPL.txt + File "/oname=$INSTDIR\Bin\XnCore.dll" ..\redist\Bin\XnCore.dll + File "/oname=$INSTDIR\Bin\XnFormats.dll" ..\redist\Bin\XnFormats.dll + File "/oname=$INSTDIR\Bin\XnDDK.dll" ..\redist\Bin\XnDDK.dll + File "/oname=$INSTDIR\Bin\XnDeviceSensorV2.dll" ..\redist\Bin\XnDeviceSensorV2.dll + File "/oname=$INSTDIR\Bin\XnDeviceFile.dll" ..\redist\Bin\XnDeviceFile.dll + File "/oname=$INSTDIR\Bin\XnSensorServer.exe" ..\redist\Bin\XnSensorServer.exe + File "/oname=$INSTDIR\Data\GlobalDefaults.ini" ..\redist\Data\GlobalDefaults.ini + + SetOutPath "$INSTDIR\Driver" + File /r ..\driver\*.* + + SetOutPath "$INSTDIR\Tools" + File /r ..\tools\*.* + + SetOutPath "$INSTDIR\SampleXMLs" + File /r ..\..\..\NITE + File /r ..\..\..\OPENNI + + ; Register it in OpenNI + ReadRegStr $OPEN_NI_INST HKLM "Software\OpenNI" "InstallDir" + ; Also add OPEN_NI_INSTALL_PATH to current environment (current environment is not updated by writing to registry) + System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("OPEN_NI_INSTALL_PATH", "$OPEN_NI_INST").r2' + ExecWait '"$OPEN_NI_INST\Bin\niReg.exe" "$INSTDIR\Bin\XnDeviceFile.dll"' + IfErrors FailedToRegister + ExecWait '"$OPEN_NI_INST\Bin\niReg.exe" "$INSTDIR\Bin\XnDeviceSensorV2.dll" "$INSTDIR\Data"' + IfErrors FailedToRegister + + ; Install the visual studio 2010 DLLs + ExecWait '"$INSTDIR\Tools\vcredist_x86.exe" /q' + + ; Install the USB Driver + ${If} ${RunningX64} + ExecWait '"$INSTDIR\Driver\dpinst-amd64.exe" /sw /el' + ${Else} + ExecWait '"$INSTDIR\Driver\dpinst-x86.exe" /sw /el' + ${EndIf} + + ; Create an uninstaller + WriteUninstaller "$INSTDIR\Uninstall EE ${EE_VER}.exe" + + ; Register the .xns file type + WriteRegStr HKCR ".xns" "" "PrimeSenseRecording" + WriteRegStr HKCR "PrimeSenseRecording" "" "PrimeSense Recording File" + WriteRegStr HKCR "PrimeSenseRecording\DefaultIcon" "" "$OPEN_NI_INST\Samples\Bin\Release\NiViewer.exe,0" + WriteRegStr HKCR "PrimeSenseRecording\shell\open\command" "" '"$OPEN_NI_INST\Samples\Bin\Release\NiViewer.exe" "%1"' + + ; Add the uninstall option into the control panel add/remove + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" "DisplayName"\ + "${EE_NAME} (remove only)" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" "UninstallString" \ + "$INSTDIR\Uninstall EE ${EE_VER}.exe" + + WriteRegStr HKLM "Software\PrimeSense\EE" "Version" "${EE_VER}" + + ; Add Env Var + WriteRegExpandStr ${env_hklm} XN_EE_INSTALL_PATH $INSTDIR + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + Goto Done + + FailedToRegister: + MessageBox MB_OK|MB_ICONSTOP "Installation Failed! Could not register module with OpenNI!" + Abort "Installation Failed! Could not register module with OpenNI!" + + Done: + +SectionEnd + + +;***************** +;*** Uninstall *** +;***************** +Section "Uninstall" + ; Unreg from OpenNI + ReadEnvStr $0 "OPEN_NI_BIN" + ExecWait '"$0\niReg.exe" -u "$INSTDIR\Bin\XnDeviceFile.dll"' + ExecWait '"$0\niReg.exe" -u "$INSTDIR\Bin\XnDeviceSensorV2.dll"' + + ; Unregister the .xns file type + DeleteRegKey HKCR ".xns" + DeleteRegKey HKCR "PrimeSenseRecording" + + ; Delete the files + RMDir /r /REBOOTOK $INSTDIR + RMDir $INSTDIR + + ; Delete the uninstall option from the control panel add/remove + DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\${EE_NAME}" + DeleteRegKey HKLM "Software\PrimeSense\EE" + + ; Remove the Env Var + DeleteRegValue ${env_hklm} XN_EE_INSTALL_PATH + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + SectionEnd \ No newline at end of file diff --git a/Platform/Win32/CreateRedist/Redist.py b/Platform/Win32/CreateRedist/Redist.py index 5e6b889..f550a0a 100644 --- a/Platform/Win32/CreateRedist/Redist.py +++ b/Platform/Win32/CreateRedist/Redist.py @@ -1,126 +1,126 @@ -#/**************************************************************************** -#* * -#* PrimeSense Sensor 5.0 Alpha * -#* Copyright (C) 2010 PrimeSense Ltd. * -#* * -#* This file is part of PrimeSense Common. * -#* * -#* PrimeSense Sensor is free software: you can redistribute it and/or modify* -#* it under the terms of the GNU Lesser General Public License as published * -#* by the Free Software Foundation, either version 3 of the License, or * -#* (at your option) any later version. * -#* * -#* PrimeSense Sensor is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Lesser General Public License for more details. * -#* * -#* You should have received a copy of the GNU Lesser General Public License * -#* along with PrimeSense Sensor. If not, see .* -#* * -#****************************************************************************/ -# - -# -import os -import sys -import shutil -import win32con, pywintypes, win32api - -ROOT_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) -REDIST_DIR = os.path.join(ROOT_DIR, "..", "Redist") -OUTPUT_DIR = os.path.join(ROOT_DIR, "Output") -SCRIPT_DIR = os.getcwd() - -def get_reg_values(reg_key, value_list): - # open the reg key - try: - reg_key = win32api.RegOpenKeyEx(*reg_key) - except pywintypes.error as e: - raise Exception("Failed to open registry key!") - # Get the values - try: - values = [(win32api.RegQueryValueEx(reg_key, name), data_type) for name, data_type in value_list] - # values list of ((value, type), expected_type) - for (value, data_type), expected in values: - if data_type != expected: - raise Exception("Bad registry value type! Expected %d, got %d instead." % (expected, data_type)) - # values okay, leave only values - values = [value for ((value, data_type), expected) in values] - except pywintypes.error as e: - raise Exception("Failed to get registry value!") - finally: - try: - win32api.RegCloseKey(reg_key) - except pywintypes.error as e: - # We don't care if reg key close failed... - pass - return tuple(values) - -# remove output dir -if os.path.exists(REDIST_DIR): - os.system("rmdir /S /Q \"" + REDIST_DIR + "\"") -if os.path.exists(OUTPUT_DIR): - os.system("rmdir /S /Q \"" + OUTPUT_DIR + "\"") -os.mkdir(REDIST_DIR) -os.mkdir(OUTPUT_DIR) - -# build -print("Building...") -try: - MSVC_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\VisualStudio\9.0") - MSVC_VALUES = [("InstallDir", win32con.REG_SZ)] - VS_INST_DIR = get_reg_values(MSVC_KEY, MSVC_VALUES)[0] - VS_NEED_UPGRADE = 0 -except Exception as e: - MSVC_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\VisualStudio\10.0") - MSVC_VALUES = [("InstallDir", win32con.REG_SZ)] - VS_INST_DIR = get_reg_values(MSVC_KEY, MSVC_VALUES)[0] - VS_NEED_UPGRADE = 1 - -os.chdir(os.path.join(ROOT_DIR, "..", "Build")) - -if VS_NEED_UPGRADE == 1: - res = os.system("\"" + VS_INST_DIR + "devenv\" " + "Engine.sln" + " /upgrade > ..\\CreateRedist\\Output\\build.log") - if res != 0: - raise Exception("build failed!") -res = os.system("\"" + VS_INST_DIR + "devenv\" " + "Engine.sln" + " /build Release > ..\\CreateRedist\\Output\\build.log") -if res != 0: - raise Exception("build failed!") -os.chdir(SCRIPT_DIR) - -print("Copying into redist folder...") - -# create folder structure -os.mkdir(os.path.join(REDIST_DIR, "Bin")) -os.mkdir(os.path.join(REDIST_DIR, "Data")) - -# copy EPL -shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "GPL.txt"), REDIST_DIR) -shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "GPL.txt"), OUTPUT_DIR) -shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "LGPL.txt"), REDIST_DIR) -shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "LGPL.txt"), OUTPUT_DIR) - -# copy binaries -RELEASE_DIR = os.path.join(ROOT_DIR, "..", "Bin", "Release") -for file in os.listdir(RELEASE_DIR): - if os.path.splitext(file)[1] in [".dll", ".exe"]: - shutil.copy(os.path.join(RELEASE_DIR, file), os.path.join(REDIST_DIR, "Bin")) - -# copy data -DATA_DIR = os.path.join(ROOT_DIR, "..", "..", "..", "Data") -for file in os.listdir(DATA_DIR): - shutil.copy(os.path.join(DATA_DIR, file), os.path.join(REDIST_DIR, "Data")) - -# create installer -print("Creating installer...") -NSIS_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NSIS") -NSIS_VALUES = [("InstallLocation", win32con.REG_EXPAND_SZ)] -NSIS_INST_DIR = get_reg_values(NSIS_KEY, NSIS_VALUES)[0] -# make installer -os.chdir(ROOT_DIR) -res = os.system("\"" + NSIS_INST_DIR + "\\makensis.exe\" " + "Engine.nsi" + " > ..\\CreateRedist\\Output\\nsis.log") -if res != 0: - raise Exception("Failed creating installer!") - -print("Done.") +#/**************************************************************************** +#* * +#* PrimeSense Sensor 5.0 Alpha * +#* Copyright (C) 2010 PrimeSense Ltd. * +#* * +#* This file is part of PrimeSense Common. * +#* * +#* PrimeSense Sensor is free software: you can redistribute it and/or modify* +#* it under the terms of the GNU Lesser General Public License as published * +#* by the Free Software Foundation, either version 3 of the License, or * +#* (at your option) any later version. * +#* * +#* PrimeSense Sensor is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Lesser General Public License for more details. * +#* * +#* You should have received a copy of the GNU Lesser General Public License * +#* along with PrimeSense Sensor. If not, see .* +#* * +#****************************************************************************/ +# + +# +import os +import sys +import shutil +import win32con, pywintypes, win32api + +ROOT_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) +REDIST_DIR = os.path.join(ROOT_DIR, "..", "Redist") +OUTPUT_DIR = os.path.join(ROOT_DIR, "Output") +SCRIPT_DIR = os.getcwd() + +def get_reg_values(reg_key, value_list): + # open the reg key + try: + reg_key = win32api.RegOpenKeyEx(*reg_key) + except pywintypes.error as e: + raise Exception("Failed to open registry key!") + # Get the values + try: + values = [(win32api.RegQueryValueEx(reg_key, name), data_type) for name, data_type in value_list] + # values list of ((value, type), expected_type) + for (value, data_type), expected in values: + if data_type != expected: + raise Exception("Bad registry value type! Expected %d, got %d instead." % (expected, data_type)) + # values okay, leave only values + values = [value for ((value, data_type), expected) in values] + except pywintypes.error as e: + raise Exception("Failed to get registry value!") + finally: + try: + win32api.RegCloseKey(reg_key) + except pywintypes.error as e: + # We don't care if reg key close failed... + pass + return tuple(values) + +# remove output dir +if os.path.exists(REDIST_DIR): + os.system("rmdir /S /Q \"" + REDIST_DIR + "\"") +if os.path.exists(OUTPUT_DIR): + os.system("rmdir /S /Q \"" + OUTPUT_DIR + "\"") +os.mkdir(REDIST_DIR) +os.mkdir(OUTPUT_DIR) + +# build +print("Building...") +try: + MSVC_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\VisualStudio\9.0") + MSVC_VALUES = [("InstallDir", win32con.REG_SZ)] + VS_INST_DIR = get_reg_values(MSVC_KEY, MSVC_VALUES)[0] + VS_NEED_UPGRADE = 0 +except Exception as e: + MSVC_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\VisualStudio\10.0") + MSVC_VALUES = [("InstallDir", win32con.REG_SZ)] + VS_INST_DIR = get_reg_values(MSVC_KEY, MSVC_VALUES)[0] + VS_NEED_UPGRADE = 1 + +os.chdir(os.path.join(ROOT_DIR, "..", "Build")) + +if VS_NEED_UPGRADE == 1: + res = os.system("\"" + VS_INST_DIR + "devenv\" " + "Engine.sln" + " /upgrade > ..\\CreateRedist\\Output\\build.log") + if res != 0: + raise Exception("build failed!") +res = os.system("\"" + VS_INST_DIR + "devenv\" " + "Engine.sln" + " /build Release > ..\\CreateRedist\\Output\\build.log") +if res != 0: + raise Exception("build failed!") +os.chdir(SCRIPT_DIR) + +print("Copying into redist folder...") + +# create folder structure +os.mkdir(os.path.join(REDIST_DIR, "Bin")) +os.mkdir(os.path.join(REDIST_DIR, "Data")) + +# copy EPL +shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "GPL.txt"), REDIST_DIR) +shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "GPL.txt"), OUTPUT_DIR) +shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "LGPL.txt"), REDIST_DIR) +shutil.copy(os.path.join(ROOT_DIR, "..", "..", "..", "LGPL.txt"), OUTPUT_DIR) + +# copy binaries +RELEASE_DIR = os.path.join(ROOT_DIR, "..", "Bin", "Release") +for file in os.listdir(RELEASE_DIR): + if os.path.splitext(file)[1] in [".dll", ".exe"]: + shutil.copy(os.path.join(RELEASE_DIR, file), os.path.join(REDIST_DIR, "Bin")) + +# copy data +DATA_DIR = os.path.join(ROOT_DIR, "..", "..", "..", "Data") +for file in os.listdir(DATA_DIR): + shutil.copy(os.path.join(DATA_DIR, file), os.path.join(REDIST_DIR, "Data")) + +# create installer +print("Creating installer...") +NSIS_KEY = (win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NSIS") +NSIS_VALUES = [("InstallLocation", win32con.REG_EXPAND_SZ)] +NSIS_INST_DIR = get_reg_values(NSIS_KEY, NSIS_VALUES)[0] +# make installer +os.chdir(ROOT_DIR) +res = os.system("\"" + NSIS_INST_DIR + "\\makensis.exe\" " + "Engine.nsi" + " > ..\\CreateRedist\\Output\\nsis.log") +if res != 0: + raise Exception("Failed creating installer!") + +print("Done.") diff --git a/Platform/Win32/Driver/dpinst.xml b/Platform/Win32/Driver/dpinst.xml index d50f5a6..fce37e7 100644 --- a/Platform/Win32/Driver/dpinst.xml +++ b/Platform/Win32/Driver/dpinst.xml @@ -1,16 +1,16 @@ - - - - - - PrimeSensor Device Driver Installer - - Welcome to the PrimeSensor Device Driver Installer! - This wizard will walk you through updating the drivers for your PrimeSensor device. - - Installing the software for your PrimeSensor device... - - Congratulations! You have finished installing your PrimeSensor device drivers! - - psdrv3.ico - + + + + + + PrimeSensor Device Driver Installer + + Welcome to the PrimeSensor Device Driver Installer! + This wizard will walk you through updating the drivers for your PrimeSensor device. + + Installing the software for your PrimeSensor device... + + Congratulations! You have finished installing your PrimeSensor device drivers! + + psdrv3.ico + diff --git a/Platform/Win32/Driver/psdrv3.inf b/Platform/Win32/Driver/psdrv3.inf index d9d3665..72156de 100644 --- a/Platform/Win32/Driver/psdrv3.inf +++ b/Platform/Win32/Driver/psdrv3.inf @@ -1,153 +1,153 @@ -;/**************************************************************************** -;* * -;* PrimeSensor Device Driver v3.x INF * -;* * -;* Author: Ziv Hendel * -;* * -;* Copyright (C) 2006 PrimeSense Ltd. All Rights Reserved. * -;* * -;* This file has been provided pursuant to a License Agreement containing * -;* restrictions on its use. This data contains valuable trade secrets * -;* and proprietary information of PrimeSense Inc. and is protected by law. * -;* * -;****************************************************************************/ -; -; Modded by avin to support the Kinect. -; - -; ================= Version section =================== - -[Version] -Signature="$WINDOWS NT$" -Class=PrimeSensor -ClassGuid={dce97d75-aef7-1980-1909-531357633001} -Provider=%PS% -DriverVer=07/13/2010,3.1.0.4 -CatalogFile=psdrv3.cat - -; ================= Class section ===================== - -[ClassInstall32] -Addreg=PrimeSensorClassReg - -[PrimeSensorClassReg] -HKR,,,0,%ClassName% -HKR,,Icon,,"-20" - -; ================= Device section ===================== - -[DestinationDirs] -DefaultDestDir = 12 ; Driver Dir - -[Manufacturer] -%MfgName%=PrimeSense,NTx86,NTamd64 - -[PrimeSense.NTx86] -%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200&MI_00 -%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200 -%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300&MI_00 -%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300 -%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400&MI_00 -%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400 -%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500&MI_00 -%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500 -%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600&MI_00 -%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600 -%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0&MI_00 -%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0 -%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE&MI_00 -%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE - -[PrimeSense.NTamd64] -%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200&MI_00 -%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200 -%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300&MI_00 -%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300 -%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400&MI_00 -%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400 -%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500&MI_00 -%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500 -%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600&MI_00 -%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600 -%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0&MI_00 -%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0 -%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE&MI_00 -%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE - -[psdrv3.Dev.NT] -CopyFiles=psdrv3.Files.Ext - -[psdrv3.Dev.NT.Services] -Addservice = psdrv3, 0x00000002, psdrv3.AddService - -[psdrv3.AddService] -DisplayName = %psdrv3.SvcDesc% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %10%\System32\Drivers\psdrv3.sys -AddReg = psdrv3.AddReg -LoadOrderGroup = Base - -[psdrv3.AddReg] -HKR,"Parameters","MaximumTransferSize",0x10001,65536 -HKR,"Parameters","DebugLevel",0x10001,2 -HKR,"Parameters","RemovableIcon",0x10001,0 - -[psdrv3.Files.Ext] -psdrv3.sys - -[SourceDisksNames.x86] -1=%Disk_Description%,,,\x86 - -[SourceDisksNames.amd64] -2=%Disk_Description%,,,\amd64 - -[SourceDisksFiles.x86] -psdrv3.sys = 1 - -[SourceDisksFiles.amd64] -psdrv3.sys = 2 - -; ================= WDF section ===================== - -[DestinationDirs] -CoInstaller_CopyFiles = 11 ; System Dir - -[psdrv3.Dev.NT.CoInstallers] -AddReg=CoInstaller_AddReg -CopyFiles=CoInstaller_CopyFiles - -[CoInstaller_CopyFiles] -WdfCoInstaller01009.dll - -[SourceDisksFiles.x86] -WdfCoInstaller01009.dll=1 - -[SourceDisksFiles.amd64] -WdfCoInstaller01009.dll=2 - -[CoInstaller_AddReg] -HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01009.dll,WdfCoInstaller" - -[psdrv3.Dev.NT.Wdf] -KmdfService = psdrv3, psdrv3_wdfsect - -[psdrv3_wdfsect] -KmdfLibraryVersion = 1.9 - -; ================= Strings section ===================== - -[Strings] -PS = "PrimeSense" -MfgName = "PrimeSense Ltd." -Disk_Description= "PrimeSensor Device Driver Installation Disk v3.x" -psdrv3.SvcDesc = "PrimeSensor Device Driver Service v3.x" -ClassName = "PrimeSensor" -USB\VID_1D27&PID_0200.DeviceDesc="PrimeSensor Development Kit 2.x" -USB\VID_1D27&PID_0300.DeviceDesc="PrimeSensor Development Kit 3.x" -USB\VID_1D27&PID_0400.DeviceDesc="PrimeSensor Development Kit 4.x" -USB\VID_1D27&PID_0500.DeviceDesc="PrimeSensor Development Kit 5.x" -USB\VID_1D27&PID_0600.DeviceDesc="PrimeSensor Reference Design 1.08x" -USB\VID_045E&PID_02B0.DeviceDesc="Kinect Motor" +;/**************************************************************************** +;* * +;* PrimeSensor Device Driver v3.x INF * +;* * +;* Author: Ziv Hendel * +;* * +;* Copyright (C) 2006 PrimeSense Ltd. All Rights Reserved. * +;* * +;* This file has been provided pursuant to a License Agreement containing * +;* restrictions on its use. This data contains valuable trade secrets * +;* and proprietary information of PrimeSense Inc. and is protected by law. * +;* * +;****************************************************************************/ +; +; Modded by avin to support the Kinect. +; + +; ================= Version section =================== + +[Version] +Signature="$WINDOWS NT$" +Class=PrimeSensor +ClassGuid={dce97d75-aef7-1980-1909-531357633001} +Provider=%PS% +DriverVer=07/13/2010,3.1.0.4 +CatalogFile=psdrv3.cat + +; ================= Class section ===================== + +[ClassInstall32] +Addreg=PrimeSensorClassReg + +[PrimeSensorClassReg] +HKR,,,0,%ClassName% +HKR,,Icon,,"-20" + +; ================= Device section ===================== + +[DestinationDirs] +DefaultDestDir = 12 ; Driver Dir + +[Manufacturer] +%MfgName%=PrimeSense,NTx86,NTamd64 + +[PrimeSense.NTx86] +%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200&MI_00 +%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200 +%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300&MI_00 +%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300 +%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400&MI_00 +%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400 +%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500&MI_00 +%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500 +%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600&MI_00 +%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600 +%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0&MI_00 +%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0 +%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE&MI_00 +%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE + +[PrimeSense.NTamd64] +%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200&MI_00 +%USB\VID_1D27&PID_0200.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0200 +%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300&MI_00 +%USB\VID_1D27&PID_0300.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0300 +%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400&MI_00 +%USB\VID_1D27&PID_0400.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0400 +%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500&MI_00 +%USB\VID_1D27&PID_0500.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0500 +%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600&MI_00 +%USB\VID_1D27&PID_0600.DeviceDesc%=psdrv3.Dev, USB\VID_1D27&PID_0600 +%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0&MI_00 +%USB\VID_045E&PID_02B0.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02B0 +%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE&MI_00 +%USB\VID_045E&PID_02AE.DeviceDesc%=psdrv3.Dev, USB\VID_045E&PID_02AE + +[psdrv3.Dev.NT] +CopyFiles=psdrv3.Files.Ext + +[psdrv3.Dev.NT.Services] +Addservice = psdrv3, 0x00000002, psdrv3.AddService + +[psdrv3.AddService] +DisplayName = %psdrv3.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\System32\Drivers\psdrv3.sys +AddReg = psdrv3.AddReg +LoadOrderGroup = Base + +[psdrv3.AddReg] +HKR,"Parameters","MaximumTransferSize",0x10001,65536 +HKR,"Parameters","DebugLevel",0x10001,2 +HKR,"Parameters","RemovableIcon",0x10001,0 + +[psdrv3.Files.Ext] +psdrv3.sys + +[SourceDisksNames.x86] +1=%Disk_Description%,,,\x86 + +[SourceDisksNames.amd64] +2=%Disk_Description%,,,\amd64 + +[SourceDisksFiles.x86] +psdrv3.sys = 1 + +[SourceDisksFiles.amd64] +psdrv3.sys = 2 + +; ================= WDF section ===================== + +[DestinationDirs] +CoInstaller_CopyFiles = 11 ; System Dir + +[psdrv3.Dev.NT.CoInstallers] +AddReg=CoInstaller_AddReg +CopyFiles=CoInstaller_CopyFiles + +[CoInstaller_CopyFiles] +WdfCoInstaller01009.dll + +[SourceDisksFiles.x86] +WdfCoInstaller01009.dll=1 + +[SourceDisksFiles.amd64] +WdfCoInstaller01009.dll=2 + +[CoInstaller_AddReg] +HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01009.dll,WdfCoInstaller" + +[psdrv3.Dev.NT.Wdf] +KmdfService = psdrv3, psdrv3_wdfsect + +[psdrv3_wdfsect] +KmdfLibraryVersion = 1.9 + +; ================= Strings section ===================== + +[Strings] +PS = "PrimeSense" +MfgName = "PrimeSense Ltd." +Disk_Description= "PrimeSensor Device Driver Installation Disk v3.x" +psdrv3.SvcDesc = "PrimeSensor Device Driver Service v3.x" +ClassName = "PrimeSensor" +USB\VID_1D27&PID_0200.DeviceDesc="PrimeSensor Development Kit 2.x" +USB\VID_1D27&PID_0300.DeviceDesc="PrimeSensor Development Kit 3.x" +USB\VID_1D27&PID_0400.DeviceDesc="PrimeSensor Development Kit 4.x" +USB\VID_1D27&PID_0500.DeviceDesc="PrimeSensor Development Kit 5.x" +USB\VID_1D27&PID_0600.DeviceDesc="PrimeSensor Reference Design 1.08x" +USB\VID_045E&PID_02B0.DeviceDesc="Kinect Motor" USB\VID_045E&PID_02AE.DeviceDesc="Kinect Camera" \ No newline at end of file diff --git a/README b/README index 1725f1a..8b3b6b1 100644 --- a/README +++ b/README @@ -1,98 +1,98 @@ -SensorKinect Module for OpenNI ------------------------------- - -Kinect Mod: ------------ - -Changes: -v0.3: - 1) Added support for high-res 1280x1024 IR and Image (at ~10 FPS) - Checkout the file OPENNI\Data\SamplesConfig.xml for usage example. - (Copy it to your OpenNI\Data dir and use NiViewer to test the different resolutions) - -v0.2: - 1) VS2010 redist will now be installed automatically. - 2) The driver will now also be installed automatically on both x86 and x64 machines. - 3) Turned off the IR projector anti-cover thingy. It is off on the Xbox360 so it must be safe and it was very annoying... - -v0.1: - 1) Added the kinect USB VID/PID to the PSDrv3 driver and to the code. - 2) Changed the packet sequence field from 16-bit to 8-bit (don't know why it's different...) - 3) Changed the image format from YUV to 8-bit uncompressed bayer in the GlobalDefaults.ini file. - 4) Fixed the software depth-to-RGB registration. (Thanks ROS.org for that!) - -PrimeSense NITE algorithm: - If you want to try it please do the following: - - 1) Install OpenNI (from www.openni.org) - 2) Install Sensor (this version...) - 3) Install NITE (from www.openni.org) - 4) Run the NiViewer sample to make sure depth & image streams are working. - 5) Run the OpenNI/NiUserTracker sample play with the skeleton. Don't forget to start with the calibration pose! (Explained in the PDFs) - 6) Try the NITE/Sample-PointViewer sample for the hand tracking demo. - - Note: All of the NITE samples are using 320x240 resolution. You need to change it to 640x480 in the XML files inside the Data directory. - I have prepared preconfigured XMLs in the "NITE\Data" dir. Just copy them to "c:\Program Files\Prime Sense\NITE\Data". - -TIPs: - 1) If you want to see the IR stream, edit the "OpenNI\Data\SamplesConfig.xml" file and change all the "Image" words into "IR". - -Release Notes: --------------- -* At the moment, the default is to compile the code with SSE3 support (this is also true for the supplied binaries). - If you have a CPU without such support, please remove the sse compiler flags from the make files. - (A good hint for this error is that you encounter an "illegal instructions" messages) -* By default, the linux kernel mounts unknown USB devices with write permissions to root only, and read-only permissions to other users. - When not running as root, this prevents communicating with the device. To fix this issue: - - Navigate to Platform/Linux-x86/Build - - run 'make install-usb-rules' - - if the device was connected, unplug and reconnect it. - This part is done automatically by the install script, but you will need to do it manually if you choose not to use the automated install. -* The device driver contains a thread for reading from the USB device. This thread should have high priority in order to function correctly. Each process using the device driver should have the CAP_SYS_NICE capability in order to raise thread priority. Failing to have that capability, will cause a failure in setting priority, consequently causing loss of data. - -Build Notes: ------------- -Windows: - Requirements: - 1) Microsoft Visual Studio 2008/2010 - 2) Python 2.x/3.x (must be at least 2.6 and above) - 3) PyWin32 - 4) NSIS 2.46 - 5) NSIS-2.46-strlen_8192.zip patch (An important patch to fix problems with adding strings to the path. you can find it in the Platform\Win32\Build\Prerequisites\ directory) - 6) Doxygen & GraphViz (to create docs...) - 7) OpenNI 1.x - - Building Sensor: - 1) Go into the directory: "Platform\Win32\CreateRedist". Run the script: "Redist.py". This will compile and prepare the redist exe files that includes everything. - 2) Install the exe you've just made which is located in Platform\Win32\CreateRedist\Output\Sensor-Win32-5.0.0.exe - The installer will also automatically register all the modules into OpenNI via the NiReg utility. - - The visual studio solution is located in: Platform\Win32\Build\EngineWin32.sln. - - Important: Please note that even though the directory is called Win32, you can also use it to compile it for 64-bit targets (AMD64/x64). - -Linux: - Requirements: - 1) GCC 4.x - 2) Python 2.6/2.7/3.0/3.1 - 3) libusb 1.0.8 (libusb-1.0-0-dev) - 4) freeglut3 (freeglut3-dev) - 5) Doxygen & GraphViz (to create docs...) - 6) OpenNI 1.x - - Building Sensor: - 1) Go into the directory: "Platform/Linux-x86/CreateRedist". Run the script: "RedistMaker". This will compile everything and create a redist package in the "Platform/Linux-x86/Redist" directory. - 2) Go into the directory: "Platform/Linux-x86/Redist". Run the script: "sudo ./install.sh" (needs to run as root) - - The install script copies key files to the following location: - Libs into: /usr/lib - Bins into: /usr/bin - Config files: /usr/etc/primesense - USB rules: /etc/udev/rules.d - Logs will be created in: /var/log/primesense - - To build the package manually, you can run make in the "Platform\Linux-x86\Build" directory. - (You can also find a SlickEdit project there...) - - Important: Please note that even though the directory is called Linux-x86, you can also use it to compile it for 64-bit targets and pretty much any other linux based environment. +SensorKinect Module for OpenNI +------------------------------ + +Kinect Mod: +----------- + +Changes: +v0.3: + 1) Added support for high-res 1280x1024 IR and Image (at ~10 FPS) + Checkout the file OPENNI\Data\SamplesConfig.xml for usage example. + (Copy it to your OpenNI\Data dir and use NiViewer to test the different resolutions) + +v0.2: + 1) VS2010 redist will now be installed automatically. + 2) The driver will now also be installed automatically on both x86 and x64 machines. + 3) Turned off the IR projector anti-cover thingy. It is off on the Xbox360 so it must be safe and it was very annoying... + +v0.1: + 1) Added the kinect USB VID/PID to the PSDrv3 driver and to the code. + 2) Changed the packet sequence field from 16-bit to 8-bit (don't know why it's different...) + 3) Changed the image format from YUV to 8-bit uncompressed bayer in the GlobalDefaults.ini file. + 4) Fixed the software depth-to-RGB registration. (Thanks ROS.org for that!) + +PrimeSense NITE algorithm: + If you want to try it please do the following: + + 1) Install OpenNI (from www.openni.org) + 2) Install Sensor (this version...) + 3) Install NITE (from www.openni.org) + 4) Run the NiViewer sample to make sure depth & image streams are working. + 5) Run the OpenNI/NiUserTracker sample play with the skeleton. Don't forget to start with the calibration pose! (Explained in the PDFs) + 6) Try the NITE/Sample-PointViewer sample for the hand tracking demo. + + Note: All of the NITE samples are using 320x240 resolution. You need to change it to 640x480 in the XML files inside the Data directory. + I have prepared preconfigured XMLs in the "NITE\Data" dir. Just copy them to "c:\Program Files\Prime Sense\NITE\Data". + +TIPs: + 1) If you want to see the IR stream, edit the "OpenNI\Data\SamplesConfig.xml" file and change all the "Image" words into "IR". + +Release Notes: +-------------- +* At the moment, the default is to compile the code with SSE3 support (this is also true for the supplied binaries). + If you have a CPU without such support, please remove the sse compiler flags from the make files. + (A good hint for this error is that you encounter an "illegal instructions" messages) +* By default, the linux kernel mounts unknown USB devices with write permissions to root only, and read-only permissions to other users. + When not running as root, this prevents communicating with the device. To fix this issue: + - Navigate to Platform/Linux-x86/Build + - run 'make install-usb-rules' + - if the device was connected, unplug and reconnect it. + This part is done automatically by the install script, but you will need to do it manually if you choose not to use the automated install. +* The device driver contains a thread for reading from the USB device. This thread should have high priority in order to function correctly. Each process using the device driver should have the CAP_SYS_NICE capability in order to raise thread priority. Failing to have that capability, will cause a failure in setting priority, consequently causing loss of data. + +Build Notes: +------------ +Windows: + Requirements: + 1) Microsoft Visual Studio 2008/2010 + 2) Python 2.x/3.x (must be at least 2.6 and above) + 3) PyWin32 + 4) NSIS 2.46 + 5) NSIS-2.46-strlen_8192.zip patch (An important patch to fix problems with adding strings to the path. you can find it in the Platform\Win32\Build\Prerequisites\ directory) + 6) Doxygen & GraphViz (to create docs...) + 7) OpenNI 1.x + + Building Sensor: + 1) Go into the directory: "Platform\Win32\CreateRedist". Run the script: "Redist.py". This will compile and prepare the redist exe files that includes everything. + 2) Install the exe you've just made which is located in Platform\Win32\CreateRedist\Output\Sensor-Win32-5.0.0.exe + The installer will also automatically register all the modules into OpenNI via the NiReg utility. + + The visual studio solution is located in: Platform\Win32\Build\EngineWin32.sln. + + Important: Please note that even though the directory is called Win32, you can also use it to compile it for 64-bit targets (AMD64/x64). + +Linux: + Requirements: + 1) GCC 4.x + 2) Python 2.6/2.7/3.0/3.1 + 3) libusb 1.0.8 (libusb-1.0-0-dev) + 4) freeglut3 (freeglut3-dev) + 5) Doxygen & GraphViz (to create docs...) + 6) OpenNI 1.x + + Building Sensor: + 1) Go into the directory: "Platform/Linux-x86/CreateRedist". Run the script: "RedistMaker". This will compile everything and create a redist package in the "Platform/Linux-x86/Redist" directory. + 2) Go into the directory: "Platform/Linux-x86/Redist". Run the script: "sudo ./install.sh" (needs to run as root) + + The install script copies key files to the following location: + Libs into: /usr/lib + Bins into: /usr/bin + Config files: /usr/etc/primesense + USB rules: /etc/udev/rules.d + Logs will be created in: /var/log/primesense + + To build the package manually, you can run make in the "Platform\Linux-x86\Build" directory. + (You can also find a SlickEdit project there...) + + Important: Please note that even though the directory is called Linux-x86, you can also use it to compile it for 64-bit targets and pretty much any other linux based environment. \ No newline at end of file diff --git a/Source/External/LibJPEG/README b/Source/External/LibJPEG/README index 911d0e8..86cc206 100644 --- a/Source/External/LibJPEG/README +++ b/Source/External/LibJPEG/README @@ -1,385 +1,385 @@ -The Independent JPEG Group's JPEG software -========================================== - -README for release 6b of 27-Mar-1998 -==================================== - -This distribution contains the sixth public release of the Independent JPEG -Group's free JPEG software. You are welcome to redistribute this software and -to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. - -Serious users of this software (particularly those incorporating it into -larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to -our electronic mailing list. Mailing list members are notified of updates -and have a chance to participate in technical discussions, etc. - -This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, -Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, -Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG -Group. - -IJG is not affiliated with the official ISO JPEG standards committee. - - -DOCUMENTATION ROADMAP -===================== - -This file contains the following sections: - -OVERVIEW General description of JPEG and the IJG software. -LEGAL ISSUES Copyright, lack of warranty, terms of distribution. -REFERENCES Where to learn more about JPEG. -ARCHIVE LOCATIONS Where to find newer versions of this software. -RELATED SOFTWARE Other stuff you should get. -FILE FORMAT WARS Software *not* to get. -TO DO Plans for future IJG releases. - -Other documentation files in the distribution are: - -User documentation: - install.doc How to configure and install the IJG software. - usage.doc Usage instructions for cjpeg, djpeg, jpegtran, - rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.doc). - wizard.doc Advanced usage instructions for JPEG wizards only. - change.log Version-to-version change highlights. -Programmer and internal documentation: - libjpeg.doc How to use the JPEG library in your own programs. - example.c Sample code for calling the JPEG library. - structure.doc Overview of the JPEG library's internal structure. - filelist.doc Road map of IJG files. - coderules.doc Coding style rules --- please read if you contribute code. - -Please read at least the files install.doc and usage.doc. Useful information -can also be found in the JPEG FAQ (Frequently Asked Questions) article. See -ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. - -If you want to understand how the JPEG code works, we suggest reading one or -more of the REFERENCES, then looking at the documentation files (in roughly -the order listed) before diving into the code. - - -OVERVIEW -======== - -This package contains C software to implement JPEG image compression and -decompression. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and gray-scale images. JPEG is intended for compressing -"real-world" scenes; line drawings, cartoons and other non-realistic images -are not its strong suit. JPEG is lossy, meaning that the output image is not -exactly identical to the input image. Hence you must not use JPEG if you -have to have identical output bits. However, on typical photographic images, -very good compression levels can be obtained with no visible change, and -remarkably high compression levels are possible if you can tolerate a -low-quality image. For more details, see the references, or just experiment -with various compression settings. - -This software implements JPEG baseline, extended-sequential, and progressive -compression processes. Provision is made for supporting all variants of these -processes, although some uncommon parameter settings aren't implemented yet. -For legal reasons, we are not distributing code for the arithmetic-coding -variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting -the hierarchical or lossless processes defined in the standard. - -We provide a set of library routines for reading and writing JPEG image files, -plus two sample applications "cjpeg" and "djpeg", which use the library to -perform conversion between JPEG and some other popular image file formats. -The library is intended to be reused in other applications. - -In order to support file conversion and viewing software, we have included -considerable functionality beyond the bare JPEG coding/decoding capability; -for example, the color quantization modules are not strictly part of JPEG -decoding, but they are essential for output to colormapped file formats or -colormapped displays. These extra functions can be compiled out of the -library if not required for a particular application. We have also included -"jpegtran", a utility for lossless transcoding between different JPEG -processes, and "rdjpgcom" and "wrjpgcom", two simple applications for -inserting and extracting textual comments in JFIF files. - -The emphasis in designing this software has been on achieving portability and -flexibility, while also making it fast enough to be useful. In particular, -the software is not intended to be read as a tutorial on JPEG. (See the -REFERENCES section for introductory material.) Rather, it is intended to -be reliable, portable, industrial-strength code. We do not claim to have -achieved that goal in every aspect of the software, but we strive for it. - -We welcome the use of this software as a component of commercial products. -No royalty is required, but we do ask for an acknowledgement in product -documentation, as described under LEGAL ISSUES. - - -LEGAL ISSUES -============ - -In plain English: - -1. We don't promise that this software works. (But if you find any bugs, - please let us know!) -2. You can use this software for whatever you want. You don't have to pay us. -3. You may not pretend that you wrote this software. If you use it in a - program, you must acknowledge somewhere in your documentation that - you've used the IJG code. - -In legalese: - -The authors make NO WARRANTY or representation, either express or implied, -with respect to this software, its quality, accuracy, merchantability, or -fitness for a particular purpose. This software is provided "AS IS", and you, -its user, assume the entire risk as to its quality and accuracy. - -This software is copyright (C) 1991-1998, Thomas G. Lane. -All Rights Reserved except as specified below. - -Permission is hereby granted to use, copy, modify, and distribute this -software (or portions thereof) for any purpose, without fee, subject to these -conditions: -(1) If any part of the source code for this software is distributed, then this -README file must be included, with this copyright and no-warranty notice -unaltered; and any additions, deletions, or changes to the original files -must be clearly indicated in accompanying documentation. -(2) If only executable code is distributed, then the accompanying -documentation must state that "this software is based in part on the work of -the Independent JPEG Group". -(3) Permission for use of this software is granted only if the user accepts -full responsibility for any undesirable consequences; the authors accept -NO LIABILITY for damages of any kind. - -These conditions apply to any software derived from or based on the IJG code, -not just to the unmodified library. If you use our work, you ought to -acknowledge us. - -Permission is NOT granted for the use of any IJG author's name or company name -in advertising or publicity relating to this software or products derived from -it. This software may be referred to only as "the Independent JPEG Group's -software". - -We specifically permit and encourage the use of this software as the basis of -commercial products, provided that all warranty or liability claims are -assumed by the product vendor. - - -ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, -sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. -ansi2knr.c is NOT covered by the above copyright and conditions, but instead -by the usual distribution terms of the Free Software Foundation; principally, -that you must include source code if you redistribute it. (See the file -ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part -of any program generated from the IJG code, this does not limit you more than -the foregoing paragraphs do. - -The Unix configuration script "configure" was produced with GNU Autoconf. -It is copyright by the Free Software Foundation but is freely distributable. -The same holds for its supporting scripts (config.guess, config.sub, -ltconfig, ltmain.sh). Another support script, install-sh, is copyright -by M.I.T. but is also freely distributable. - -It appears that the arithmetic coding option of the JPEG spec is covered by -patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot -legally be used without obtaining one or more licenses. For this reason, -support for arithmetic coding has been removed from the free JPEG software. -(Since arithmetic coding provides only a marginal gain over the unpatented -Huffman mode, it is unlikely that very many implementations will support it.) -So far as we are aware, there are no patent restrictions on the remaining -code. - -The IJG distribution formerly included code to read and write GIF files. -To avoid entanglement with the Unisys LZW patent, GIF reading support has -been removed altogether, and the GIF writer has been simplified to produce -"uncompressed GIFs". This technique does not use the LZW algorithm; the -resulting GIF files are larger than usual, but are readable by all standard -GIF decoders. - -We are required to state that - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." - - -REFERENCES -========== - -We highly recommend reading one or more of these references before trying to -understand the innards of the JPEG software. - -The best short technical introduction to the JPEG compression algorithm is - Wallace, Gregory K. "The JPEG Still Picture Compression Standard", - Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. -(Adjacent articles in that issue discuss MPEG motion picture compression, -applications of JPEG, and related topics.) If you don't have the CACM issue -handy, a PostScript file containing a revised version of Wallace's article is -available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually -a preprint for an article that appeared in IEEE Trans. Consumer Electronics) -omits the sample images that appeared in CACM, but it includes corrections -and some added material. Note: the Wallace article is copyright ACM and IEEE, -and it may not be used for commercial purposes. - -A somewhat less technical, more leisurely introduction to JPEG can be found in -"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by -M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides -good explanations and example C code for a multitude of compression methods -including JPEG. It is an excellent source if you are comfortable reading C -code but don't know much about data compression in general. The book's JPEG -sample code is far from industrial-strength, but when you are ready to look -at a full implementation, you've got one here... - -The best full description of JPEG is the textbook "JPEG Still Image Data -Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published -by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. -The book includes the complete text of the ISO JPEG standards (DIS 10918-1 -and draft DIS 10918-2). This is by far the most complete exposition of JPEG -in existence, and we highly recommend it. - -The JPEG standard itself is not available electronically; you must order a -paper copy through ISO or ITU. (Unless you feel a need to own a certified -official copy, we recommend buying the Pennebaker and Mitchell book instead; -it's much cheaper and includes a great deal of useful explanatory material.) -In the USA, copies of the standard may be ordered from ANSI Sales at (212) -642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI -doesn't take credit card orders, but Global does.) It's not cheap: as of -1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% -shipping/handling. The standard is divided into two parts, Part 1 being the -actual specification, while Part 2 covers compliance testing methods. Part 1 -is titled "Digital Compression and Coding of Continuous-tone Still Images, -Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS -10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of -Continuous-tone Still Images, Part 2: Compliance testing" and has document -numbers ISO/IEC IS 10918-2, ITU-T T.83. - -Some extensions to the original JPEG standard are defined in JPEG Part 3, -a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG -currently does not support any Part 3 extensions. - -The JPEG standard does not specify all details of an interchangeable file -format. For the omitted details we follow the "JFIF" conventions, revision -1.02. A copy of the JFIF spec is available from: - Literature Department - C-Cube Microsystems, Inc. - 1778 McCarthy Blvd. - Milpitas, CA 95035 - phone (408) 944-6300, fax (408) 944-6314 -A PostScript version of this document is available by FTP at -ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text -version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing -the figures. - -The TIFF 6.0 file format specification can be obtained by FTP from -ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme -found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. -IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). -Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 -(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or -from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision -of the TIFF spec will replace the 6.0 JPEG design with the Note's design. -Although IJG's own code does not support TIFF/JPEG, the free libtiff library -uses our library to implement TIFF/JPEG per the Note. libtiff is available -from ftp://ftp.sgi.com/graphics/tiff/. - - -ARCHIVE LOCATIONS -================= - -The "official" archive site for this software is ftp.uu.net (Internet -address 192.48.96.9). The most recent released version can always be found -there in directory graphics/jpeg. This particular version will be archived -as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have -direct Internet access, UUNET's archives are also available via UUCP; contact -help@uunet.uu.net for information on retrieving files that way. - -Numerous Internet sites maintain copies of the UUNET files. However, only -ftp.uu.net is guaranteed to have the latest official version. - -You can also obtain this software in DOS-compatible "zip" archive format from -the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or -on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 -"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net -release. - -The JPEG FAQ (Frequently Asked Questions) article is a useful source of -general information about JPEG. It is updated constantly and therefore is -not included in this distribution. The FAQ is posted every two weeks to -Usenet newsgroups comp.graphics.misc, news.answers, and other groups. -It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ -and other news.answers archive sites, including the official news.answers -archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. -If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu -with body - send usenet/news.answers/jpeg-faq/part1 - send usenet/news.answers/jpeg-faq/part2 - - -RELATED SOFTWARE -================ - -Numerous viewing and image manipulation programs now support JPEG. (Quite a -few of them use this library to do so.) The JPEG FAQ described above lists -some of the more popular free and shareware viewers, and tells where to -obtain them on Internet. - -If you are on a Unix machine, we highly recommend Jef Poskanzer's free -PBMPLUS software, which provides many useful operations on PPM-format image -files. In particular, it can convert PPM images to and from a wide range of -other formats, thus making cjpeg/djpeg considerably more useful. The latest -version is distributed by the NetPBM group, and is available from numerous -sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. -Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; -you are likely to have difficulty making it work on any non-Unix machine. - -A different free JPEG implementation, written by the PVRG group at Stanford, -is available from ftp://havefun.stanford.edu/pub/jpeg/. This program -is designed for research and experimentation rather than production use; -it is slower, harder to use, and less portable than the IJG code, but it -is easier to read and modify. Also, the PVRG code supports lossless JPEG, -which we do not. (On the other hand, it doesn't do progressive JPEG.) - - -FILE FORMAT WARS -================ - -Some JPEG programs produce files that are not compatible with our library. -The root of the problem is that the ISO JPEG committee failed to specify a -concrete file format. Some vendors "filled in the blanks" on their own, -creating proprietary formats that no one else could read. (For example, none -of the early commercial JPEG implementations for the Macintosh were able to -exchange compressed files.) - -The file format we have adopted is called JFIF (see REFERENCES). This format -has been agreed to by a number of major commercial JPEG vendors, and it has -become the de facto standard. JFIF is a minimal or "low end" representation. -We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF -Technical Note #2) for "high end" applications that need to record a lot of -additional data about an image. TIFF/JPEG is fairly new and not yet widely -supported, unfortunately. - -The upcoming JPEG Part 3 standard defines a file format called SPIFF. -SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should -be able to read the most common variant of SPIFF. SPIFF has some technical -advantages over JFIF, but its major claim to fame is simply that it is an -official standard rather than an informal one. At this point it is unclear -whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto -standard. IJG intends to support SPIFF once the standard is frozen, but we -have not decided whether it should become our default output format or not. -(In any case, our decoder will remain capable of reading JFIF indefinitely.) - -Various proprietary file formats incorporating JPEG compression also exist. -We have little or no sympathy for the existence of these formats. Indeed, -one of the original reasons for developing this free software was to help -force convergence on common, open format standards for JPEG files. Don't -use a proprietary file format! - - -TO DO -===== - -The major thrust for v7 will probably be improvement of visual quality. -The current method for scaling the quantization tables is known not to be -very good at low Q values. We also intend to investigate block boundary -smoothing, "poor man's variable quantization", and other means of improving -quality-vs-file-size performance without sacrificing compatibility. - -In future versions, we are considering supporting some of the upcoming JPEG -Part 3 extensions --- principally, variable quantization and the SPIFF file -format. - -As always, speeding things up is of great interest. - -Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. +The Independent JPEG Group's JPEG software +========================================== + +README for release 6b of 27-Mar-1998 +==================================== + +This distribution contains the sixth public release of the Independent JPEG +Group's free JPEG software. You are welcome to redistribute this software and +to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + +Serious users of this software (particularly those incorporating it into +larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to +our electronic mailing list. Mailing list members are notified of updates +and have a chance to participate in technical discussions, etc. + +This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, +Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, +Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG +Group. + +IJG is not affiliated with the official ISO JPEG standards committee. + + +DOCUMENTATION ROADMAP +===================== + +This file contains the following sections: + +OVERVIEW General description of JPEG and the IJG software. +LEGAL ISSUES Copyright, lack of warranty, terms of distribution. +REFERENCES Where to learn more about JPEG. +ARCHIVE LOCATIONS Where to find newer versions of this software. +RELATED SOFTWARE Other stuff you should get. +FILE FORMAT WARS Software *not* to get. +TO DO Plans for future IJG releases. + +Other documentation files in the distribution are: + +User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. +Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + +Please read at least the files install.doc and usage.doc. Useful information +can also be found in the JPEG FAQ (Frequently Asked Questions) article. See +ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + +If you want to understand how the JPEG code works, we suggest reading one or +more of the REFERENCES, then looking at the documentation files (in roughly +the order listed) before diving into the code. + + +OVERVIEW +======== + +This package contains C software to implement JPEG image compression and +decompression. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. JPEG is intended for compressing +"real-world" scenes; line drawings, cartoons and other non-realistic images +are not its strong suit. JPEG is lossy, meaning that the output image is not +exactly identical to the input image. Hence you must not use JPEG if you +have to have identical output bits. However, on typical photographic images, +very good compression levels can be obtained with no visible change, and +remarkably high compression levels are possible if you can tolerate a +low-quality image. For more details, see the references, or just experiment +with various compression settings. + +This software implements JPEG baseline, extended-sequential, and progressive +compression processes. Provision is made for supporting all variants of these +processes, although some uncommon parameter settings aren't implemented yet. +For legal reasons, we are not distributing code for the arithmetic-coding +variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting +the hierarchical or lossless processes defined in the standard. + +We provide a set of library routines for reading and writing JPEG image files, +plus two sample applications "cjpeg" and "djpeg", which use the library to +perform conversion between JPEG and some other popular image file formats. +The library is intended to be reused in other applications. + +In order to support file conversion and viewing software, we have included +considerable functionality beyond the bare JPEG coding/decoding capability; +for example, the color quantization modules are not strictly part of JPEG +decoding, but they are essential for output to colormapped file formats or +colormapped displays. These extra functions can be compiled out of the +library if not required for a particular application. We have also included +"jpegtran", a utility for lossless transcoding between different JPEG +processes, and "rdjpgcom" and "wrjpgcom", two simple applications for +inserting and extracting textual comments in JFIF files. + +The emphasis in designing this software has been on achieving portability and +flexibility, while also making it fast enough to be useful. In particular, +the software is not intended to be read as a tutorial on JPEG. (See the +REFERENCES section for introductory material.) Rather, it is intended to +be reliable, portable, industrial-strength code. We do not claim to have +achieved that goal in every aspect of the software, but we strive for it. + +We welcome the use of this software as a component of commercial products. +No royalty is required, but we do ask for an acknowledgement in product +documentation, as described under LEGAL ISSUES. + + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + +REFERENCES +========== + +We highly recommend reading one or more of these references before trying to +understand the innards of the JPEG software. + +The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. +(Adjacent articles in that issue discuss MPEG motion picture compression, +applications of JPEG, and related topics.) If you don't have the CACM issue +handy, a PostScript file containing a revised version of Wallace's article is +available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +a preprint for an article that appeared in IEEE Trans. Consumer Electronics) +omits the sample images that appeared in CACM, but it includes corrections +and some added material. Note: the Wallace article is copyright ACM and IEEE, +and it may not be used for commercial purposes. + +A somewhat less technical, more leisurely introduction to JPEG can be found in +"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by +M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides +good explanations and example C code for a multitude of compression methods +including JPEG. It is an excellent source if you are comfortable reading C +code but don't know much about data compression in general. The book's JPEG +sample code is far from industrial-strength, but when you are ready to look +at a full implementation, you've got one here... + +The best full description of JPEG is the textbook "JPEG Still Image Data +Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published +by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. +The book includes the complete text of the ISO JPEG standards (DIS 10918-1 +and draft DIS 10918-2). This is by far the most complete exposition of JPEG +in existence, and we highly recommend it. + +The JPEG standard itself is not available electronically; you must order a +paper copy through ISO or ITU. (Unless you feel a need to own a certified +official copy, we recommend buying the Pennebaker and Mitchell book instead; +it's much cheaper and includes a great deal of useful explanatory material.) +In the USA, copies of the standard may be ordered from ANSI Sales at (212) +642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI +doesn't take credit card orders, but Global does.) It's not cheap: as of +1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% +shipping/handling. The standard is divided into two parts, Part 1 being the +actual specification, while Part 2 covers compliance testing methods. Part 1 +is titled "Digital Compression and Coding of Continuous-tone Still Images, +Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS +10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of +Continuous-tone Still Images, Part 2: Compliance testing" and has document +numbers ISO/IEC IS 10918-2, ITU-T T.83. + +Some extensions to the original JPEG standard are defined in JPEG Part 3, +a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG +currently does not support any Part 3 extensions. + +The JPEG standard does not specify all details of an interchangeable file +format. For the omitted details we follow the "JFIF" conventions, revision +1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 +A PostScript version of this document is available by FTP at +ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text +version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing +the figures. + +The TIFF 6.0 file format specification can be obtained by FTP from +ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme +found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. +IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). +Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 +(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or +from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +of the TIFF spec will replace the 6.0 JPEG design with the Note's design. +Although IJG's own code does not support TIFF/JPEG, the free libtiff library +uses our library to implement TIFF/JPEG per the Note. libtiff is available +from ftp://ftp.sgi.com/graphics/tiff/. + + +ARCHIVE LOCATIONS +================= + +The "official" archive site for this software is ftp.uu.net (Internet +address 192.48.96.9). The most recent released version can always be found +there in directory graphics/jpeg. This particular version will be archived +as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have +direct Internet access, UUNET's archives are also available via UUCP; contact +help@uunet.uu.net for information on retrieving files that way. + +Numerous Internet sites maintain copies of the UUNET files. However, only +ftp.uu.net is guaranteed to have the latest official version. + +You can also obtain this software in DOS-compatible "zip" archive format from +the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or +on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 +"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net +release. + +The JPEG FAQ (Frequently Asked Questions) article is a useful source of +general information about JPEG. It is updated constantly and therefore is +not included in this distribution. The FAQ is posted every two weeks to +Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ +and other news.answers archive sites, including the official news.answers +archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. +If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu +with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + +RELATED SOFTWARE +================ + +Numerous viewing and image manipulation programs now support JPEG. (Quite a +few of them use this library to do so.) The JPEG FAQ described above lists +some of the more popular free and shareware viewers, and tells where to +obtain them on Internet. + +If you are on a Unix machine, we highly recommend Jef Poskanzer's free +PBMPLUS software, which provides many useful operations on PPM-format image +files. In particular, it can convert PPM images to and from a wide range of +other formats, thus making cjpeg/djpeg considerably more useful. The latest +version is distributed by the NetPBM group, and is available from numerous +sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. +Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; +you are likely to have difficulty making it work on any non-Unix machine. + +A different free JPEG implementation, written by the PVRG group at Stanford, +is available from ftp://havefun.stanford.edu/pub/jpeg/. This program +is designed for research and experimentation rather than production use; +it is slower, harder to use, and less portable than the IJG code, but it +is easier to read and modify. Also, the PVRG code supports lossless JPEG, +which we do not. (On the other hand, it doesn't do progressive JPEG.) + + +FILE FORMAT WARS +================ + +Some JPEG programs produce files that are not compatible with our library. +The root of the problem is that the ISO JPEG committee failed to specify a +concrete file format. Some vendors "filled in the blanks" on their own, +creating proprietary formats that no one else could read. (For example, none +of the early commercial JPEG implementations for the Macintosh were able to +exchange compressed files.) + +The file format we have adopted is called JFIF (see REFERENCES). This format +has been agreed to by a number of major commercial JPEG vendors, and it has +become the de facto standard. JFIF is a minimal or "low end" representation. +We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF +Technical Note #2) for "high end" applications that need to record a lot of +additional data about an image. TIFF/JPEG is fairly new and not yet widely +supported, unfortunately. + +The upcoming JPEG Part 3 standard defines a file format called SPIFF. +SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should +be able to read the most common variant of SPIFF. SPIFF has some technical +advantages over JFIF, but its major claim to fame is simply that it is an +official standard rather than an informal one. At this point it is unclear +whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto +standard. IJG intends to support SPIFF once the standard is frozen, but we +have not decided whether it should become our default output format or not. +(In any case, our decoder will remain capable of reading JFIF indefinitely.) + +Various proprietary file formats incorporating JPEG compression also exist. +We have little or no sympathy for the existence of these formats. Indeed, +one of the original reasons for developing this free software was to help +force convergence on common, open format standards for JPEG files. Don't +use a proprietary file format! + + +TO DO +===== + +The major thrust for v7 will probably be improvement of visual quality. +The current method for scaling the quantization tables is known not to be +very good at low Q values. We also intend to investigate block boundary +smoothing, "poor man's variable quantization", and other means of improving +quality-vs-file-size performance without sacrificing compatibility. + +In future versions, we are considering supporting some of the upcoming JPEG +Part 3 extensions --- principally, variable quantization and the SPIFF file +format. + +As always, speeding things up is of great interest. + +Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/Source/External/LibJPEG/cderror.h b/Source/External/LibJPEG/cderror.h index c19d38f..70435e1 100644 --- a/Source/External/LibJPEG/cderror.h +++ b/Source/External/LibJPEG/cderror.h @@ -1,132 +1,132 @@ -/* - * cderror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the cjpeg/djpeg - * applications. These strings are not needed as part of the JPEG library - * proper. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef CDERROR_H -#define CDERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* CDERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ - -#ifdef BMP_SUPPORTED -JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") -JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") -JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") -JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") -JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") -JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") -JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") -JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") -JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") -JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") -JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") -#endif /* BMP_SUPPORTED */ - -#ifdef GIF_SUPPORTED -JMESSAGE(JERR_GIF_BUG, "GIF output got confused") -JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") -JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") -JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") -JMESSAGE(JERR_GIF_NOT, "Not a GIF file") -JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") -JMESSAGE(JTRC_GIF_BADVERSION, - "Warning: unexpected GIF version number '%c%c%c'") -JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") -JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") -JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") -JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") -JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") -JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") -#endif /* GIF_SUPPORTED */ - -#ifdef PPM_SUPPORTED -JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") -JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") -JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") -JMESSAGE(JTRC_PGM, "%ux%u PGM image") -JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") -JMESSAGE(JTRC_PPM, "%ux%u PPM image") -JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") -#endif /* PPM_SUPPORTED */ - -#ifdef RLE_SUPPORTED -JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") -JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") -JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") -JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") -JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") -JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") -JMESSAGE(JERR_RLE_NOT, "Not an RLE file") -JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") -JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") -JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") -JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") -JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") -JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") -JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") -#endif /* RLE_SUPPORTED */ - -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") -JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") -JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") -JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") -JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") -JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") -#else -JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") -#endif /* TARGA_SUPPORTED */ - -JMESSAGE(JERR_BAD_CMAP_FILE, - "Color map file is invalid or of unsupported format") -JMESSAGE(JERR_TOO_MANY_COLORS, - "Output file format cannot handle %d colormap entries") -JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_UNKNOWN_FORMAT, - "Unrecognized input file format --- perhaps you need -targa") -#else -JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") -#endif -JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTADDONCODE -} ADDON_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE +/* + * cderror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the cjpeg/djpeg + * applications. These strings are not needed as part of the JPEG library + * proper. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef CDERROR_H +#define CDERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* CDERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ + +#ifdef BMP_SUPPORTED +JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") +JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") +JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") +JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") +JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") +JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") +JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") +JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") +JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") +JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") +#endif /* BMP_SUPPORTED */ + +#ifdef GIF_SUPPORTED +JMESSAGE(JERR_GIF_BUG, "GIF output got confused") +JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") +JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") +JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") +JMESSAGE(JERR_GIF_NOT, "Not a GIF file") +JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") +JMESSAGE(JTRC_GIF_BADVERSION, + "Warning: unexpected GIF version number '%c%c%c'") +JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") +JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") +JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") +JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") +JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") +JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") +#endif /* GIF_SUPPORTED */ + +#ifdef PPM_SUPPORTED +JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") +JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") +JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") +JMESSAGE(JTRC_PGM, "%ux%u PGM image") +JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") +JMESSAGE(JTRC_PPM, "%ux%u PPM image") +JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") +#endif /* PPM_SUPPORTED */ + +#ifdef RLE_SUPPORTED +JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") +JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") +JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") +JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") +JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") +JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") +JMESSAGE(JERR_RLE_NOT, "Not an RLE file") +JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") +JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") +JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") +JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") +JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") +JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") +JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") +#endif /* RLE_SUPPORTED */ + +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") +JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") +JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") +JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") +JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") +JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") +#else +JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") +#endif /* TARGA_SUPPORTED */ + +JMESSAGE(JERR_BAD_CMAP_FILE, + "Color map file is invalid or of unsupported format") +JMESSAGE(JERR_TOO_MANY_COLORS, + "Output file format cannot handle %d colormap entries") +JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_UNKNOWN_FORMAT, + "Unrecognized input file format --- perhaps you need -targa") +#else +JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") +#endif +JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTADDONCODE +} ADDON_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE diff --git a/Source/External/LibJPEG/jcapimin.c b/Source/External/LibJPEG/jcapimin.c index 493af5c..54fb8c5 100644 --- a/Source/External/LibJPEG/jcapimin.c +++ b/Source/External/LibJPEG/jcapimin.c @@ -1,280 +1,280 @@ -/* - * jcapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the compression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-compression case or the transcoding-only - * case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jcapistd.c. But also see jcparam.c for - * parameter-setup helper routines, jcomapi.c for routines shared by - * compression and decompression, and jctrans.c for the transcoding case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG compression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL(void) -jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) -{ - int i; - - /* Guard against version mismatches between library and caller. */ - cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ - if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); - if (structsize != SIZEOF(struct jpeg_compress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); - - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; - } - cinfo->is_decompressor = FALSE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->dest = NULL; - - cinfo->comp_info = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - cinfo->script_space = NULL; - - cinfo->input_gamma = 1.0; /* in case application forgets */ - - /* OK, I'm ready */ - cinfo->global_state = CSTATE_START; -} - - -/* - * Destruction of a JPEG compression object - */ - -GLOBAL(void) -jpeg_destroy_compress (j_compress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG compression operation, - * but don't destroy the object itself. - */ - -GLOBAL(void) -jpeg_abort_compress (j_compress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Forcibly suppress or un-suppress all quantization and Huffman tables. - * Marks all currently defined tables as already written (if suppress) - * or not written (if !suppress). This will control whether they get emitted - * by a subsequent jpeg_start_compress call. - * - * This routine is exported for use by applications that want to produce - * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but - * since it is called by jpeg_start_compress, we put it here --- otherwise - * jcparam.o would be linked whether the application used it or not. - */ - -GLOBAL(void) -jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) -{ - int i; - JQUANT_TBL * qtbl; - JHUFF_TBL * htbl; - - for (i = 0; i < NUM_QUANT_TBLS; i++) { - if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) - qtbl->sent_table = suppress; - } - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; - if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; - } -} - - -/* - * Finish JPEG compression. - * - * If a multipass operating mode was selected, this may do a great deal of - * work including most of the actual output. - */ - -GLOBAL(void) -jpeg_finish_compress (j_compress_ptr cinfo) -{ - JDIMENSION iMCU_row; - - if (cinfo->global_state == CSTATE_SCANNING || - cinfo->global_state == CSTATE_RAW_OK) { - /* Terminate first pass */ - if (cinfo->next_scanline < cinfo->image_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_pass) (cinfo); - } else if (cinfo->global_state != CSTATE_WRCOEFS) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any remaining passes */ - while (! cinfo->master->is_last_pass) { - (*cinfo->master->prepare_for_pass) (cinfo); - for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) iMCU_row; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* We bypass the main controller and invoke coef controller directly; - * all work is being done from the coefficient buffer. - */ - if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - } - (*cinfo->master->finish_pass) (cinfo); - } - /* Write EOI, do final cleanup */ - (*cinfo->marker->write_file_trailer) (cinfo); - (*cinfo->dest->term_destination) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); -} - - -/* - * Write a special marker. - * This is only recommended for writing COM or APPn markers. - * Must be called after jpeg_start_compress() and before - * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). - */ - -GLOBAL(void) -jpeg_write_marker (j_compress_ptr cinfo, int marker, - const JOCTET *dataptr, unsigned int datalen) -{ - JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); - - if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); - write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ - while (datalen--) { - (*write_marker_byte) (cinfo, *dataptr); - dataptr++; - } -} - -/* Same, but piecemeal. */ - -GLOBAL(void) -jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) -{ - if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); -} - -GLOBAL(void) -jpeg_write_m_byte (j_compress_ptr cinfo, int val) -{ - (*cinfo->marker->write_marker_byte) (cinfo, val); -} - - -/* - * Alternate compression function: just write an abbreviated table file. - * Before calling this, all parameters and a data destination must be set up. - * - * To produce a pair of files containing abbreviated tables and abbreviated - * image data, one would proceed as follows: - * - * initialize JPEG object - * set JPEG parameters - * set destination to table file - * jpeg_write_tables(cinfo); - * set destination to image file - * jpeg_start_compress(cinfo, FALSE); - * write data... - * jpeg_finish_compress(cinfo); - * - * jpeg_write_tables has the side effect of marking all tables written - * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress - * will not re-emit the tables unless it is passed write_all_tables=TRUE. - */ - -GLOBAL(void) -jpeg_write_tables (j_compress_ptr cinfo) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Initialize the marker writer ... bit of a crock to do it here. */ - jinit_marker_writer(cinfo); - /* Write them tables! */ - (*cinfo->marker->write_tables_only) (cinfo); - /* And clean up. */ - (*cinfo->dest->term_destination) (cinfo); - /* - * In library releases up through v6a, we called jpeg_abort() here to free - * any working memory allocated by the destination manager and marker - * writer. Some applications had a problem with that: they allocated space - * of their own from the library memory manager, and didn't want it to go - * away during write_tables. So now we do nothing. This will cause a - * memory leak if an app calls write_tables repeatedly without doing a full - * compression cycle or otherwise resetting the JPEG object. However, that - * seems less bad than unexpectedly freeing memory in the normal case. - * An app that prefers the old behavior can call jpeg_abort for itself after - * each call to jpeg_write_tables(). - */ -} +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/Source/External/LibJPEG/jcapistd.c b/Source/External/LibJPEG/jcapistd.c index fed66ca..c0320b1 100644 --- a/Source/External/LibJPEG/jcapistd.c +++ b/Source/External/LibJPEG/jcapistd.c @@ -1,161 +1,161 @@ -/* - * jcapistd.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the compression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-compression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_compress, it will end up linking in the entire compressor. - * We thus must separate this file from jcapimin.c to avoid linking the - * whole compression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Compression initialization. - * Before calling this, all parameters and a data destination must be set up. - * - * We require a write_all_tables parameter as a failsafe check when writing - * multiple datastreams from the same compression object. Since prior runs - * will have left all the tables marked sent_table=TRUE, a subsequent run - * would emit an abbreviated stream (no tables) by default. This may be what - * is wanted, but for safety's sake it should not be the default behavior: - * programmers should have to make a deliberate choice to emit abbreviated - * images. Therefore the documentation and examples should encourage people - * to pass write_all_tables=TRUE; then it will take active thought to do the - * wrong thing. - */ - -GLOBAL(void) -jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (write_all_tables) - jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ - - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ - jinit_compress_master(cinfo); - /* Set up for the first pass */ - (*cinfo->master->prepare_for_pass) (cinfo); - /* Ready for application to drive first pass through jpeg_write_scanlines - * or jpeg_write_raw_data. - */ - cinfo->next_scanline = 0; - cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); -} - - -/* - * Write some scanlines of data to the JPEG compressor. - * - * The return value will be the number of lines actually written. - * This should be less than the supplied num_lines only in case that - * the data destination module has requested suspension of the compressor, - * or if more than image_height scanlines are passed in. - * - * Note: we warn about excess calls to jpeg_write_scanlines() since - * this likely signals an application programmer error. However, - * excess scanlines passed in the last valid call are *silently* ignored, - * so that the application need not adjust num_lines for end-of-image - * when using a multiple-scanline buffer. - */ - -GLOBAL(JDIMENSION) -jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) -{ - JDIMENSION row_ctr, rows_left; - - if (cinfo->global_state != CSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->next_scanline >= cinfo->image_height) - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Give master control module another chance if this is first call to - * jpeg_write_scanlines. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_scanlines. - */ - if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); - - /* Ignore any extra scanlines at bottom of image. */ - rows_left = cinfo->image_height - cinfo->next_scanline; - if (num_lines > rows_left) - num_lines = rows_left; - - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); - cinfo->next_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to write raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL(JDIMENSION) -jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != CSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->next_scanline >= cinfo->image_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Give master control module another chance if this is first call to - * jpeg_write_raw_data. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_raw_data. - */ - if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); - - /* Verify that at least one iMCU row has been passed. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; - if (num_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Directly compress the row. */ - if (! (*cinfo->coef->compress_data) (cinfo, data)) { - /* If compressor did not consume the whole row, suspend processing. */ - return 0; - } - - /* OK, we processed one iMCU row. */ - cinfo->next_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->coef->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/Source/External/LibJPEG/jccoefct.c b/Source/External/LibJPEG/jccoefct.c index c713b85..1963ddb 100644 --- a/Source/External/LibJPEG/jccoefct.c +++ b/Source/External/LibJPEG/jccoefct.c @@ -1,449 +1,449 @@ -/* - * jccoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for compression. - * This controller is the top level of the JPEG compressor proper. - * The coefficient buffer lies between forward-DCT and entropy encoding steps. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* We use a full-image coefficient buffer when doing Huffman optimization, - * and also for writing multiple-scan JPEG files. In all cases, the DCT - * step is run during the first pass, and subsequent passes need only read - * the buffered coefficients. - */ -#ifdef ENTROPY_OPT_SUPPORTED -#define FULL_COEF_BUFFER_SUPPORTED -#else -#ifdef C_MULTISCAN_FILES_SUPPORTED -#define FULL_COEF_BUFFER_SUPPORTED -#endif -#endif - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_coef_controller pub; /* public fields */ - - JDIMENSION iMCU_row_num; /* iMCU row # within image */ - JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* For single-pass compression, it's sufficient to buffer just one MCU - * (although this may prove a bit slow in practice). We allocate a - * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each - * MCU constructed and sent. (On 80x86, the workspace is FAR even though - * it's not really very big; this is to keep the module interfaces unchanged - * when a large coefficient buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays. - */ - JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; - - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - - -/* Forward declarations */ -METHODDEF(boolean) compress_data - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#ifdef FULL_COEF_BUFFER_SUPPORTED -METHODDEF(boolean) compress_first_pass - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -METHODDEF(boolean) compress_output - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->mcu_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - coef->iMCU_row_num = 0; - start_iMCU_row(cinfo); - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (coef->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_data; - break; -#ifdef FULL_COEF_BUFFER_SUPPORTED - case JBUF_SAVE_AND_PASS: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_first_pass; - break; - case JBUF_CRANK_DEST: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_output; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data in the single-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(boolean) -compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, bi, ci, yindex, yoffset, blockcnt; - JDIMENSION ypos, xpos; - jpeg_component_info *compptr; - - /* Loop to write as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Determine where data comes from in input_buf and do the DCT thing. - * Each call on forward_DCT processes a horizontal row of DCT blocks - * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks - * sequentially. Dummy blocks at the right or bottom edge are filled in - * specially. The data in them does not matter for image reconstruction, - * so we fill them with values that will encode to the smallest amount of - * data, viz: all zeroes in the AC entries, DC entries equal to previous - * block's DC value. (Thanks to Thomas Kinsman for this idea.) - */ - blkn = 0; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - xpos = MCU_col_num * compptr->MCU_sample_width; - ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION) blockcnt); - if (blockcnt < compptr->MCU_width) { - /* Create some dummy blocks at the right edge of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], - (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); - for (bi = blockcnt; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; - } - } - } else { - /* Create a row of dummy blocks at the bottom of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn], - compptr->MCU_width * SIZEOF(JBLOCK)); - for (bi = 0; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; - } - } - blkn += compptr->MCU_width; - ypos += DCTSIZE; - } - } - /* Try to write the MCU. In event of a suspension failure, we will - * re-DCT the MCU on restart (a bit inefficient, could be fixed...) - */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - - -#ifdef FULL_COEF_BUFFER_SUPPORTED - -/* - * Process some data in the first pass of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * This amount of data is read from the source buffer, DCT'd and quantized, - * and saved into the virtual arrays. We also generate suitable dummy blocks - * as needed at the right and lower edges. (The dummy blocks are constructed - * in the virtual arrays, which have been padded appropriately.) This makes - * it possible for subsequent passes not to worry about real vs. dummy blocks. - * - * We must also emit the data to the entropy encoder. This is conveniently - * done by calling compress_output() after we've loaded the current strip - * of the virtual arrays. - * - * NB: input_buf contains a plane for each component in image. All - * components are DCT'd and loaded into the virtual arrays in this pass. - * However, it may be that only a subset of the components are emitted to - * the entropy encoder during this first pass; be careful about looking - * at the scan-dependent variables (MCU dimensions, etc). - */ - -METHODDEF(boolean) -compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION blocks_across, MCUs_across, MCUindex; - int bi, ci, h_samp_factor, block_row, block_rows, ndummy; - JCOEF lastDC; - jpeg_component_info *compptr; - JBLOCKARRAY buffer; - JBLOCKROW thisblockrow, lastblockrow; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (coef->iMCU_row_num < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here, since may not be set! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - blocks_across = compptr->width_in_blocks; - h_samp_factor = compptr->h_samp_factor; - /* Count number of dummy blocks to be added at the right margin. */ - ndummy = (int) (blocks_across % h_samp_factor); - if (ndummy > 0) - ndummy = h_samp_factor - ndummy; - /* Perform DCT for all non-dummy blocks in this iMCU row. Each call - * on forward_DCT processes a complete horizontal row of DCT blocks. - */ - for (block_row = 0; block_row < block_rows; block_row++) { - thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION) (block_row * DCTSIZE), - (JDIMENSION) 0, blocks_across); - if (ndummy > 0) { - /* Create dummy blocks at the right edge of the image. */ - thisblockrow += blocks_across; /* => first dummy block */ - jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); - lastDC = thisblockrow[-1][0]; - for (bi = 0; bi < ndummy; bi++) { - thisblockrow[bi][0] = lastDC; - } - } - } - /* If at end of image, create dummy block rows as needed. - * The tricky part here is that within each MCU, we want the DC values - * of the dummy blocks to match the last real block's DC value. - * This squeezes a few more bytes out of the resulting file... - */ - if (coef->iMCU_row_num == last_iMCU_row) { - blocks_across += ndummy; /* include lower right corner */ - MCUs_across = blocks_across / h_samp_factor; - for (block_row = block_rows; block_row < compptr->v_samp_factor; - block_row++) { - thisblockrow = buffer[block_row]; - lastblockrow = buffer[block_row-1]; - jzero_far((void FAR *) thisblockrow, - (size_t) (blocks_across * SIZEOF(JBLOCK))); - for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { - lastDC = lastblockrow[h_samp_factor-1][0]; - for (bi = 0; bi < h_samp_factor; bi++) { - thisblockrow[bi][0] = lastDC; - } - thisblockrow += h_samp_factor; /* advance to next MCU in row */ - lastblockrow += h_samp_factor; - } - } - } - } - /* NB: compress_output will increment iMCU_row_num if successful. - * A suspension return will result in redoing all the work above next time. - */ - - /* Emit data to the entropy encoder, sharing code with subsequent passes */ - return compress_output(cinfo, input_buf); -} - - -/* - * Process some data in subsequent passes of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - -METHODDEF(boolean) -compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. - * NB: during first pass, this is safe only because the buffers will - * already be aligned properly, so jmemmgr.c won't need to do any I/O. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - -#endif /* FULL_COEF_BUFFER_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL(void) -jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_c_coef_controller *) coef; - coef->pub.start_pass = start_pass_coef; - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef FULL_COEF_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - int ci; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - } -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->whole_image[0] = NULL; /* flag for no virtual arrays */ - } -} +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/Source/External/LibJPEG/jccolor.c b/Source/External/LibJPEG/jccolor.c index 2663724..0a8a4b5 100644 --- a/Source/External/LibJPEG/jccolor.c +++ b/Source/External/LibJPEG/jccolor.c @@ -1,459 +1,459 @@ -/* - * jccolor.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_converter pub; /* public fields */ - - /* Private state for RGB->YCC conversion */ - INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ -} my_color_converter; - -typedef my_color_converter * my_cconvert_ptr; - - -/**************** RGB -> YCbCr conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, - * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and - * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) - * were not represented exactly. Now we sacrifice exact representation of - * maximum red and maximum blue in order to get exact grayscales. - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times R,G,B for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included - * in the tables to save adding them separately in the inner loop. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L< Y section */ -#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ -#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ -#define R_CB_OFF (3*(MAXJSAMPLE+1)) -#define G_CB_OFF (4*(MAXJSAMPLE+1)) -#define B_CB_OFF (5*(MAXJSAMPLE+1)) -#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ -#define G_CR_OFF (6*(MAXJSAMPLE+1)) -#define B_CR_OFF (7*(MAXJSAMPLE+1)) -#define TABLE_SIZE (8*(MAXJSAMPLE+1)) - - -/* - * Initialize for RGB->YCC colorspace conversion. - */ - -METHODDEF(void) -rgb_ycc_start (j_compress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - INT32 * rgb_ycc_tab; - INT32 i; - - /* Allocate and fill in the conversion tables. */ - cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); - - for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; - rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; - /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. - * This ensures that the maximum output will round to MAXJSAMPLE - * not MAXJSAMPLE+1, and thus that we don't have to range-limit. - */ - rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -/* B=>Cb and R=>Cr tables are the same - rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -*/ - rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; - rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * - * Note that we change from the application's interleaved-pixel format - * to our internal noninterleaved, one-plane-per-component format. - * The input buffer is therefore three times as wide as the output buffer. - * - * A starting row offset is provided only for the output buffer. The caller - * can easily adjust the passed input_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF(void) -rgb_ycc_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); - } - } -} - - -/**************** Cases other than RGB -> YCbCr **************/ - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles RGB->grayscale conversion, which is the same - * as the RGB->Y portion of RGB->YCbCr. - * We assume rgb_ycc_start has been called (we only use the Y tables). - */ - -METHODDEF(void) -rgb_gray_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* Y */ - outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles Adobe-style CMYK->YCCK conversion, - * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same - * conversion as above, while passing K (black) unchanged. - * We assume rgb_ycc_start has been called. - */ - -METHODDEF(void) -cmyk_ycck_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2, outptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - outptr3 = output_buf[3][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); - g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); - b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); - /* K passes through as-is */ - outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ - inptr += 4; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles grayscale output with no conversion. - * The source can be either plain grayscale or YCbCr (since Y == gray). - */ - -METHODDEF(void) -grayscale_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - int instride = cinfo->input_components; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ - inptr += instride; - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles multi-component colorspaces without conversion. - * We assume input_components == num_components. - */ - -METHODDEF(void) -null_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - register int ci; - int nc = cinfo->num_components; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - /* It seems fastest to make a separate pass for each component. */ - for (ci = 0; ci < nc; ci++) { - inptr = *input_buf; - outptr = output_buf[ci][output_row]; - for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ - inptr += nc; - } - } - input_buf++; - output_row++; - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF(void) -null_method (j_compress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for input colorspace conversion. - */ - -GLOBAL(void) -jinit_color_converter (j_compress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_converter)); - cinfo->cconvert = (struct jpeg_color_converter *) cconvert; - /* set start_pass to null method until we find out differently */ - cconvert->pub.start_pass = null_method; - - /* Make sure input_components agrees with in_color_space */ - switch (cinfo->in_color_space) { - case JCS_GRAYSCALE: - if (cinfo->input_components != 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - case JCS_RGB: -#if RGB_PIXELSIZE != 3 - if (cinfo->input_components != RGB_PIXELSIZE) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; -#endif /* else share code with YCbCr */ - - case JCS_YCbCr: - if (cinfo->input_components != 3) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->input_components != 4) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->input_components < 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - } - - /* Check num_components, set conversion method based on requested space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_GRAYSCALE) - cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_RGB: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_ycc_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = cmyk_ycck_convert; - } else if (cinfo->in_color_space == JCS_YCCK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - default: /* allow null conversion of JCS_UNKNOWN */ - if (cinfo->jpeg_color_space != cinfo->in_color_space || - cinfo->num_components != cinfo->input_components) - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - cconvert->pub.color_convert = null_convert; - break; - } -} +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_ycc_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/Source/External/LibJPEG/jcdctmgr.c b/Source/External/LibJPEG/jcdctmgr.c index e3f90dc..61fa79b 100644 --- a/Source/External/LibJPEG/jcdctmgr.c +++ b/Source/External/LibJPEG/jcdctmgr.c @@ -1,387 +1,387 @@ -/* - * jcdctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the forward-DCT management logic. - * This code selects a particular DCT implementation to be used, - * and it performs related housekeeping chores including coefficient - * quantization. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_forward_dct pub; /* public fields */ - - /* Pointer to the DCT routine actually in use */ - forward_DCT_method_ptr do_dct; - - /* The actual post-DCT divisors --- not identical to the quant table - * entries, because of scaling (especially for an unnormalized DCT). - * Each table is given in normal array order. - */ - DCTELEM * divisors[NUM_QUANT_TBLS]; - -#ifdef DCT_FLOAT_SUPPORTED - /* Same as above for the floating-point case. */ - float_DCT_method_ptr do_float_dct; - FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; -#endif -} my_fdct_controller; - -typedef my_fdct_controller * my_fdct_ptr; - - -/* - * Initialize for a processing pass. - * Verify that all referenced Q-tables are present, and set up - * the divisor table for each one. - * In the current implementation, DCT of all components is done during - * the first pass, even if only some components will be output in the - * first scan. Hence all components should be examined here. - */ - -METHODDEF(void) -start_pass_fdctmgr (j_compress_ptr cinfo) -{ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - int ci, qtblno, i; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - DCTELEM * dtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - qtblno = compptr->quant_tbl_no; - /* Make sure specified quantization table is present */ - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - /* For LL&M IDCT method, divisors are equal to raw quantization - * coefficients multiplied by 8 (to counteract scaling). - */ - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Perform forward DCT on one or more blocks of a component. - * - * The input samples are taken from the sample_data[] array starting at - * position start_row/start_col, and moving to the right for any additional - * blocks. The quantized coefficients are returned in coef_blocks[]. - */ - -METHODDEF(void) -forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) -/* This version is used for integer DCT implementations. */ -{ - /* This routine is heavily used, so it's worth coding it tightly. */ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - forward_DCT_method_ptr do_dct = fdct->do_dct; - DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; - DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ - JDIMENSION bi; - - sample_data += start_row; /* fold in the vertical offset once */ - - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - } - } -#endif - } - } - - /* Perform the DCT */ - (*do_dct) (workspace); - - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register DCTELEM temp, qval; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; - - for (i = 0; i < DCTSIZE2; i++) { - qval = divisors[i]; - temp = workspace[i]; - /* Divide the coefficient value by qval, ensuring proper rounding. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * - * In most files, at least half of the output values will be zero - * (at default quantization settings, more like three-quarters...) - * so we should ensure that this case is fast. On many machines, - * a comparison is enough cheaper than a divide to make a special test - * a win. Since both inputs will be nonnegative, we need only test - * for a < b to discover whether a/b is 0. - * If your machine's division is fast enough, define FAST_DIVIDE. - */ -#ifdef FAST_DIVIDE -#define DIVIDE_BY(a,b) a /= b -#else -#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 -#endif - if (temp < 0) { - temp = -temp; - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - temp = -temp; - } else { - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - } - output_ptr[i] = (JCOEF) temp; - } - } - } -} - - -#ifdef DCT_FLOAT_SUPPORTED - -METHODDEF(void) -forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) -/* This version is used for floating-point DCT implementations. */ -{ - /* This routine is heavily used, so it's worth coding it tightly. */ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - float_DCT_method_ptr do_dct = fdct->do_float_dct; - FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; - FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ - JDIMENSION bi; - - sample_data += start_row; /* fold in the vertical offset once */ - - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = (FAST_FLOAT) - (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - } - } -#endif - } - } - - /* Perform the DCT */ - (*do_dct) (workspace); - - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register FAST_FLOAT temp; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; - - for (i = 0; i < DCTSIZE2; i++) { - /* Apply the quantization and scaling factor */ - temp = workspace[i] * divisors[i]; - /* Round to nearest integer. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * The maximum coefficient size is +-16K (for 12-bit data), so this - * code should work for either 16-bit or 32-bit ints. - */ - output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); - } - } - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ - - -/* - * Initialize FDCT manager. - */ - -GLOBAL(void) -jinit_forward_dct (j_compress_ptr cinfo) -{ - my_fdct_ptr fdct; - int i; - - fdct = (my_fdct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_fdct_controller)); - cinfo->fdct = (struct jpeg_forward_dct *) fdct; - fdct->pub.start_pass = start_pass_fdctmgr; - - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_islow; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_ifast; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; - fdct->do_float_dct = jpeg_fdct_float; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - - /* Mark divisor tables unallocated */ - for (i = 0; i < NUM_QUANT_TBLS; i++) { - fdct->divisors[i] = NULL; -#ifdef DCT_FLOAT_SUPPORTED - fdct->float_divisors[i] = NULL; -#endif - } -} +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} my_fdct_controller; + +typedef my_fdct_controller * my_fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct; + int i; + + fdct = (my_fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_fdct_controller)); + cinfo->fdct = (struct jpeg_forward_dct *) fdct; + fdct->pub.start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->pub.forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/Source/External/LibJPEG/jchuff.c b/Source/External/LibJPEG/jchuff.c index 16d9366..f235250 100644 --- a/Source/External/LibJPEG/jchuff.c +++ b/Source/External/LibJPEG/jchuff.c @@ -1,909 +1,909 @@ -/* - * jchuff.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines. - * - * Much of the complexity here has to do with supporting output suspension. - * If the data destination module demands suspension, we want to be able to - * back up to the start of the current MCU. To do this, we copy state - * variables into local working storage, and update them back to the - * permanent JPEG objects only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jcphuff.c */ - - -/* Expanded entropy encoder object for Huffman encoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).put_buffer = (src).put_buffer, \ - (dest).put_bits = (src).put_bits, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ - - savable_state saved; /* Bit buffer & DC state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ - long * dc_count_ptrs[NUM_HUFF_TBLS]; - long * ac_count_ptrs[NUM_HUFF_TBLS]; -#endif -} huff_entropy_encoder; - -typedef huff_entropy_encoder * huff_entropy_ptr; - -/* Working state while writing an MCU. - * This struct contains all the fields that are needed by subroutines. - */ - -typedef struct { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - savable_state cur; /* Current bit buffer & DC state */ - j_compress_ptr cinfo; /* dump_buffer needs access to this */ -} working_state; - - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); -#ifdef ENTROPY_OPT_SUPPORTED -METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); -#endif - - -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. - */ - -METHODDEF(void) -start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - entropy->pub.encode_mcu = encode_mcu_gather; - entropy->pub.finish_pass = finish_pass_gather; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - entropy->pub.encode_mcu = encode_mcu_huff; - entropy->pub.finish_pass = finish_pass_huff; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[dctbl] == NULL) - entropy->dc_count_ptrs[dctbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); - if (entropy->ac_count_ptrs[actbl] == NULL) - entropy->ac_count_ptrs[actbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); -#endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jcphuff.c. - */ - -GLOBAL(void) -jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl) -{ - JHUFF_TBL *htbl; - c_derived_tbl *dtbl; - int p, i, l, lastp, si, maxsymbol; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ - if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (c_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_derived_tbl)); - dtbl = *pdtbl; - - /* Figure C.1: make table of Huffman code length for each symbol */ - - p = 0; - for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - lastp = p; - - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - - code = 0; - si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - si++; - } - - /* Figure C.3: generate encoding tables */ - /* These are code and size indexed by symbol value */ - - /* Set all codeless symbols to have code length 0; - * this lets us detect duplicate VAL entries here, and later - * allows emit_bits to detect any attempt to emit such symbols. - */ - MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); - - /* This is also a convenient place to check for out-of-range - * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..15 for DC. (We could constrain them further - * based on data depth and mode, but this seems enough.) - */ - maxsymbol = isDC ? 15 : 255; - - for (p = 0; p < lastp; p++) { - i = htbl->huffval[p]; - if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - dtbl->ehufco[i] = huffcode[p]; - dtbl->ehufsi[i] = huffsize[p]; - } -} - - -/* Outputting bytes to the file */ - -/* Emit a byte, taking 'action' if must suspend. */ -#define emit_byte(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } - - -LOCAL(boolean) -dump_buffer (working_state * state) -/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ -{ - struct jpeg_destination_mgr * dest = state->cinfo->dest; - - if (! (*dest->empty_output_buffer) (state->cinfo)) - return FALSE; - /* After a successful buffer dump, must reset buffer pointers */ - state->next_output_byte = dest->next_output_byte; - state->free_in_buffer = dest->free_in_buffer; - return TRUE; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - - put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; - } - - state->cur.put_buffer = put_buffer; /* update state variables */ - state->cur.put_bits = put_bits; - - return TRUE; -} - - -LOCAL(boolean) -flush_bits (working_state * state) -{ - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ - state->cur.put_bits = 0; - return TRUE; -} - - -/* Encode a single block's worth of coefficients */ - -LOCAL(boolean) -encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, - c_derived_tbl *dctbl, c_derived_tbl *actbl) -{ - register int temp, temp2; - register int nbits; - register int k, r, i; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = temp2 = block[0] - last_dc_val; - - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) - return FALSE; - r -= 16; - } - - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) - return FALSE; - - return TRUE; -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(boolean) -emit_restart (working_state * state, int restart_num) -{ - int ci; - - if (! flush_bits(state)) - return FALSE; - - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; - - /* The restart counter is not updated until we successfully write the MCU. */ - - return TRUE; -} - - -/* - * Encode and output one MCU's worth of Huffman-compressed coefficients. - */ - -METHODDEF(boolean) -encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - int blkn, ci; - jpeg_component_info * compptr; - - /* Load up working state */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) - return FALSE; - } - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - if (! encode_one_block(&state, - MCU_data[blkn][0], state.cur.last_dc_val[ci], - entropy->dc_derived_tbls[compptr->dc_tbl_no], - entropy->ac_derived_tbls[compptr->ac_tbl_no])) - return FALSE; - /* Update last_dc_val */ - state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - /* Completed MCU, so update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed scan. - */ - -METHODDEF(void) -finish_pass_huff (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Flush out the last data */ - if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); -} - - -/* - * Huffman coding optimization. - * - * We first scan the supplied data and count the number of uses of each symbol - * that is to be Huffman-coded. (This process MUST agree with the code above.) - * Then we build a Huffman coding tree for the observed counts. - * Symbols which are not needed at all for the particular image are not - * assigned any code, which saves space in the DHT marker as well as in - * the compressed data. - */ - -#ifdef ENTROPY_OPT_SUPPORTED - - -/* Process a single block's worth of coefficients */ - -LOCAL(void) -htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, - long dc_counts[], long ac_counts[]) -{ - register int temp; - register int nbits; - register int k, r; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = block[0] - last_dc_val; - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count the Huffman symbol for the number of bits */ - dc_counts[nbits]++; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - ac_counts[0xF0]++; - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count Huffman symbol for run length / number of bits */ - ac_counts[(r << 4) + nbits]++; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - ac_counts[0]++; -} - - -/* - * Trial-encode one MCU's worth of Huffman-compressed coefficients. - * No data is actually output, so no suspension return is possible. - */ - -METHODDEF(boolean) -encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn, ci; - jpeg_component_info * compptr; - - /* Take care of restart intervals if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Update restart state */ - entropy->restarts_to_go = cinfo->restart_interval; - } - entropy->restarts_to_go--; - } - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], - entropy->dc_count_ptrs[compptr->dc_tbl_no], - entropy->ac_count_ptrs[compptr->ac_tbl_no]); - entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - return TRUE; -} - - -/* - * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. - * - * The JPEG standard requires that no symbol be assigned a codeword of all - * one bits (so that padding bits added at the end of a compressed segment - * can't look like a valid code). Because of the canonical ordering of - * codewords, this just means that there must be an unused slot in the - * longest codeword length category. Section K.2 of the JPEG spec suggests - * reserving such a slot by pretending that symbol 256 is a valid symbol - * with count 1. In theory that's not optimal; giving it count zero but - * including it in the symbol set anyway should give a better Huffman code. - * But the theoretically better code actually seems to come out worse in - * practice, because it produces more all-ones bytes (which incur stuffed - * zero bytes in the final file). In any case the difference is tiny. - * - * The JPEG standard requires Huffman codes to be no more than 16 bits long. - * If some symbols have a very small but nonzero probability, the Huffman tree - * must be adjusted to meet the code length restriction. We currently use - * the adjustment method suggested in JPEG section K.2. This method is *not* - * optimal; it may not choose the best possible limited-length code. But - * typically only very-low-frequency symbols will be given less-than-optimal - * lengths, so the code is almost optimal. Experimental comparisons against - * an optimal limited-length-code algorithm indicate that the difference is - * microscopic --- usually less than a hundredth of a percent of total size. - * So the extra complexity of an optimal algorithm doesn't seem worthwhile. - */ - -GLOBAL(void) -jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) -{ -#define MAX_CLEN 32 /* assumed maximum initial code length */ - UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ - int codesize[257]; /* codesize[k] = code length of symbol k */ - int others[257]; /* next symbol in current branch of tree */ - int c1, c2; - int p, i, j; - long v; - - /* This algorithm is explained in section K.2 of the JPEG standard */ - - MEMZERO(bits, SIZEOF(bits)); - MEMZERO(codesize, SIZEOF(codesize)); - for (i = 0; i < 257; i++) - others[i] = -1; /* init links to empty */ - - freq[256] = 1; /* make sure 256 has a nonzero count */ - /* Including the pseudo-symbol 256 in the Huffman procedure guarantees - * that no real symbol is given code-value of all ones, because 256 - * will be placed last in the largest codeword category. - */ - - /* Huffman's basic algorithm to assign optimal code lengths to symbols */ - - for (;;) { - /* Find the smallest nonzero frequency, set c1 = its symbol */ - /* In case of ties, take the larger symbol number */ - c1 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v) { - v = freq[i]; - c1 = i; - } - } - - /* Find the next smallest nonzero frequency, set c2 = its symbol */ - /* In case of ties, take the larger symbol number */ - c2 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v && i != c1) { - v = freq[i]; - c2 = i; - } - } - - /* Done if we've merged everything into one frequency */ - if (c2 < 0) - break; - - /* Else merge the two counts/trees */ - freq[c1] += freq[c2]; - freq[c2] = 0; - - /* Increment the codesize of everything in c1's tree branch */ - codesize[c1]++; - while (others[c1] >= 0) { - c1 = others[c1]; - codesize[c1]++; - } - - others[c1] = c2; /* chain c2 onto c1's tree branch */ - - /* Increment the codesize of everything in c2's tree branch */ - codesize[c2]++; - while (others[c2] >= 0) { - c2 = others[c2]; - codesize[c2]++; - } - } - - /* Now count the number of symbols of each code length */ - for (i = 0; i <= 256; i++) { - if (codesize[i]) { - /* The JPEG standard seems to think that this can't happen, */ - /* but I'm paranoid... */ - if (codesize[i] > MAX_CLEN) - ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); - - bits[codesize[i]]++; - } - } - - /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure - * Huffman procedure assigned any such lengths, we must adjust the coding. - * Here is what the JPEG spec says about how this next bit works: - * Since symbols are paired for the longest Huffman code, the symbols are - * removed from this length category two at a time. The prefix for the pair - * (which is one bit shorter) is allocated to one of the pair; then, - * skipping the BITS entry for that prefix length, a code word from the next - * shortest nonzero BITS entry is converted into a prefix for two code words - * one bit longer. - */ - - for (i = MAX_CLEN; i > 16; i--) { - while (bits[i] > 0) { - j = i - 2; /* find length of new prefix to be used */ - while (bits[j] == 0) - j--; - - bits[i] -= 2; /* remove two symbols */ - bits[i-1]++; /* one goes in this length */ - bits[j+1] += 2; /* two new symbols in this length */ - bits[j]--; /* symbol of this length is now a prefix */ - } - } - - /* Remove the count for the pseudo-symbol 256 from the largest codelength */ - while (bits[i] == 0) /* find largest codelength still in use */ - i--; - bits[i]--; - - /* Return final symbol counts (only for lengths 0..16) */ - MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); - - /* Return a list of the symbols sorted by code length */ - /* It's not real clear to me why we don't need to consider the codelength - * changes made above, but the JPEG spec seems to think this works. - */ - p = 0; - for (i = 1; i <= MAX_CLEN; i++) { - for (j = 0; j <= 255; j++) { - if (codesize[j] == i) { - htbl->huffval[p] = (UINT8) j; - p++; - } - } - } - - /* Set sent_table FALSE so updated table will be written to JPEG file. */ - htbl->sent_table = FALSE; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did_dc[NUM_HUFF_TBLS]; - boolean did_ac[NUM_HUFF_TBLS]; - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did_dc, SIZEOF(did_dc)); - MEMZERO(did_ac, SIZEOF(did_ac)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; - } - if (! did_ac[actbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); - did_ac[actbl] = TRUE; - } - } -} - - -#endif /* ENTROPY_OPT_SUPPORTED */ - - -/* - * Module initialization routine for Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_huff_encoder (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_huff; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED - entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; -#endif - } -} +/* + * jchuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jcphuff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcu = encode_mcu_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcu = encode_mcu_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jcphuff.c. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * Note this is also used by jcphuff.c. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/Source/External/LibJPEG/jchuff.h b/Source/External/LibJPEG/jchuff.h index 8c02c09..a9599fc 100644 --- a/Source/External/LibJPEG/jchuff.h +++ b/Source/External/LibJPEG/jchuff.h @@ -1,47 +1,47 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_c_derived_tbl - JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN(void) jpeg_gen_optimal_table - JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jMkCDerived +#define jpeg_gen_optimal_table jGenOptTbl +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/Source/External/LibJPEG/jcinit.c b/Source/External/LibJPEG/jcinit.c index 19de8d0..5efffe3 100644 --- a/Source/External/LibJPEG/jcinit.c +++ b/Source/External/LibJPEG/jcinit.c @@ -1,72 +1,72 @@ -/* - * jcinit.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains initialization logic for the JPEG compressor. - * This routine is in charge of selecting the modules to be executed and - * making an initialization call to each one. - * - * Logically, this code belongs in jcmaster.c. It's split out because - * linking this routine implies linking the entire compression library. - * For a transcoding-only application, we want to be able to use jcmaster.c - * without linking in the whole library. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Master selection of compression modules. - * This is done once at the start of processing an image. We determine - * which modules will be used and give them appropriate initialization calls. - */ - -GLOBAL(void) -jinit_compress_master (j_compress_ptr cinfo) -{ - /* Initialize master control (includes parameter checking/processing) */ - jinit_c_master_control(cinfo, FALSE /* full compression */); - - /* Preprocessing */ - if (! cinfo->raw_data_in) { - jinit_color_converter(cinfo); - jinit_downsampler(cinfo); - jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); - } - /* Forward DCT */ - jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); - } - - /* Need a full-image coefficient buffer in any multi-pass mode. */ - jinit_c_coef_controller(cinfo, - (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); - jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); - - jinit_marker_writer(cinfo); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Write the datastream header (SOI) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ - (*cinfo->marker->write_file_header) (cinfo); -} +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/Source/External/LibJPEG/jcmainct.c b/Source/External/LibJPEG/jcmainct.c index 231c50b..176e562 100644 --- a/Source/External/LibJPEG/jcmainct.c +++ b/Source/External/LibJPEG/jcmainct.c @@ -1,293 +1,293 @@ -/* - * jcmainct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for compression. - * The main buffer lies between the pre-processor and the JPEG - * compressor proper; it holds downsampled data in the JPEG colorspace. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Note: currently, there is no operating mode in which a full-image buffer - * is needed at this step. If there were, that mode could not be used with - * "raw data" input, since this module is bypassed in that case. However, - * we've left the code here for possible use in special applications. - */ -#undef FULL_MAIN_BUFFER_SUPPORTED - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_main_controller pub; /* public fields */ - - JDIMENSION cur_iMCU_row; /* number of current iMCU row */ - JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ - boolean suspended; /* remember if we suspended output */ - J_BUF_MODE pass_mode; /* current operating mode */ - - /* If using just a strip buffer, this points to the entire set of buffers - * (we allocate one for each component). In the full-image case, this - * points to the currently accessible strips of the virtual arrays. - */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - -#ifdef FULL_MAIN_BUFFER_SUPPORTED - /* If using full-image storage, this array holds pointers to virtual-array - * control blocks for each component. Unused if not full-image storage. - */ - jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; -#endif -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - - -/* Forward declarations */ -METHODDEF(void) process_data_simple_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); -#ifdef FULL_MAIN_BUFFER_SUPPORTED -METHODDEF(void) process_data_buffer_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - - /* Do nothing in raw-data mode. */ - if (cinfo->raw_data_in) - return; - - mainptr->cur_iMCU_row = 0; /* initialize counters */ - mainptr->rowgroup_ctr = 0; - mainptr->suspended = FALSE; - mainptr->pass_mode = pass_mode; /* save mode for use by process_data */ - - switch (pass_mode) { - case JBUF_PASS_THRU: -#ifdef FULL_MAIN_BUFFER_SUPPORTED - if (mainptr->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - mainptr->pub.process_data = process_data_simple_main; - break; -#ifdef FULL_MAIN_BUFFER_SUPPORTED - case JBUF_SAVE_SOURCE: - case JBUF_CRANK_DEST: - case JBUF_SAVE_AND_PASS: - if (mainptr->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - mainptr->pub.process_data = process_data_buffer_main; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This routine handles the simple pass-through mode, - * where we have only a strip buffer. - */ - -METHODDEF(void) -process_data_simple_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - - while (mainptr->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Read input data if we haven't filled the main buffer yet */ - if (mainptr->rowgroup_ctr < DCTSIZE) - (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - mainptr->buffer, &mainptr->rowgroup_ctr, - (JDIMENSION) DCTSIZE); - - /* If we don't have a full iMCU row buffered, return to application for - * more data. Note that preprocessor will always pad to fill the iMCU row - * at the bottom of the image. - */ - if (mainptr->rowgroup_ctr != DCTSIZE) - return; - - /* Send the completed row to the compressor */ - if (! (*cinfo->coef->compress_data) (cinfo, mainptr->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! mainptr->suspended) { - (*in_row_ctr)--; - mainptr->suspended = TRUE; - } - return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (mainptr->suspended) { - (*in_row_ctr)++; - mainptr->suspended = FALSE; - } - mainptr->rowgroup_ctr = 0; - mainptr->cur_iMCU_row++; - } -} - - -#ifdef FULL_MAIN_BUFFER_SUPPORTED - -/* - * Process some data. - * This routine handles all of the modes that use a full-size buffer. - */ - -METHODDEF(void) -process_data_buffer_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - int ci; - jpeg_component_info *compptr; - boolean writing = (mainptr->pass_mode != JBUF_CRANK_DEST); - - while (mainptr->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Realign the virtual buffers if at the start of an iMCU row. */ - if (mainptr->rowgroup_ctr == 0) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - mainptr->buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, mainptr->whole_image[ci], - mainptr->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); - } - /* In a read pass, pretend we just read some source data. */ - if (! writing) { - *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; - mainptr->rowgroup_ctr = DCTSIZE; - } - } - - /* If a write pass, read input data until the current iMCU row is full. */ - /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ - if (writing) { - (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - mainptr->buffer, &mainptr->rowgroup_ctr, - (JDIMENSION) DCTSIZE); - /* Return to application if we need more data to fill the iMCU row. */ - if (mainptr->rowgroup_ctr < DCTSIZE) - return; - } - - /* Emit data, unless this is a sink-only pass. */ - if (mainptr->pass_mode != JBUF_SAVE_SOURCE) { - if (! (*cinfo->coef->compress_data) (cinfo, mainptr->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! mainptr->suspended) { - (*in_row_ctr)--; - mainptr->suspended = TRUE; - } - return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (mainptr->suspended) { - (*in_row_ctr)++; - mainptr->suspended = FALSE; - } - } - - /* If get here, we are done with this iMCU row. Mark buffer empty. */ - mainptr->rowgroup_ctr = 0; - mainptr->cur_iMCU_row++; - } -} - -#endif /* FULL_MAIN_BUFFER_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL(void) -jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr mainptr; - int ci; - jpeg_component_info *compptr; - - mainptr = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_c_main_controller *) mainptr; - mainptr->pub.start_pass = start_pass_main; - - /* We don't need to create a buffer in raw-data mode. */ - if (cinfo->raw_data_in) - return; - - /* Create the buffer. It holds downsampled data, so each component - * may be of a different size. - */ - if (need_full_buffer) { -#ifdef FULL_MAIN_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component */ - /* Note we pad the bottom to a multiple of the iMCU height */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - mainptr->whole_image[ci] = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor) * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - } else { -#ifdef FULL_MAIN_BUFFER_SUPPORTED - mainptr->whole_image[0] = NULL; /* flag for no virtual arrays */ -#endif - /* Allocate a strip buffer for each component */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - mainptr->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } - } -} +/* + * jcmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + mainptr->cur_iMCU_row = 0; /* initialize counters */ + mainptr->rowgroup_ctr = 0; + mainptr->suspended = FALSE; + mainptr->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (mainptr->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + mainptr->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (mainptr->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + mainptr->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + + while (mainptr->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mainptr->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mainptr->buffer, &mainptr->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (mainptr->rowgroup_ctr != DCTSIZE) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, mainptr->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mainptr->suspended) { + (*in_row_ctr)--; + mainptr->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mainptr->suspended) { + (*in_row_ctr)++; + mainptr->suspended = FALSE; + } + mainptr->rowgroup_ctr = 0; + mainptr->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (mainptr->pass_mode != JBUF_CRANK_DEST); + + while (mainptr->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (mainptr->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainptr->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mainptr->whole_image[ci], + mainptr->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; + mainptr->rowgroup_ctr = DCTSIZE; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mainptr->buffer, &mainptr->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (mainptr->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (mainptr->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, mainptr->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mainptr->suspended) { + (*in_row_ctr)--; + mainptr->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mainptr->suspended) { + (*in_row_ctr)++; + mainptr->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + mainptr->rowgroup_ctr = 0; + mainptr->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mainptr; + int ci; + jpeg_component_info *compptr; + + mainptr = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) mainptr; + mainptr->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainptr->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor) * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + mainptr->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } + } +} diff --git a/Source/External/LibJPEG/jcmarker.c b/Source/External/LibJPEG/jcmarker.c index 0d3ca5e..3d1e6c6 100644 --- a/Source/External/LibJPEG/jcmarker.c +++ b/Source/External/LibJPEG/jcmarker.c @@ -1,664 +1,664 @@ -/* - * jcmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to write JPEG datastream markers. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* Private state */ - -typedef struct { - struct jpeg_marker_writer pub; /* public fields */ - - unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ -} my_marker_writer; - -typedef my_marker_writer * my_marker_ptr; - - -/* - * Basic output routines. - * - * Note that we do not support suspension while writing a marker. - * Therefore, an application using suspension must ensure that there is - * enough buffer space for the initial markers (typ. 600-700 bytes) before - * calling jpeg_start_compress, and enough space to write the trailing EOI - * (a few bytes) before calling jpeg_finish_compress. Multipass compression - * modes are not supported at all with suspension, so those two are the only - * points where markers will be written. - */ - -LOCAL(void) -emit_byte (j_compress_ptr cinfo, int val) -/* Emit a byte */ -{ - struct jpeg_destination_mgr * dest = cinfo->dest; - - *(dest->next_output_byte)++ = (JOCTET) val; - if (--dest->free_in_buffer == 0) { - if (! (*dest->empty_output_buffer) (cinfo)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - } -} - - -LOCAL(void) -emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) -/* Emit a marker code */ -{ - emit_byte(cinfo, 0xFF); - emit_byte(cinfo, (int) mark); -} - - -LOCAL(void) -emit_2bytes (j_compress_ptr cinfo, int value) -/* Emit a 2-byte integer; these are always MSB first in JPEG files */ -{ - emit_byte(cinfo, (value >> 8) & 0xFF); - emit_byte(cinfo, value & 0xFF); -} - - -/* - * Routines to write specific marker types. - */ - -LOCAL(int) -emit_dqt (j_compress_ptr cinfo, int index) -/* Emit a DQT marker */ -/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ -{ - JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; - int prec; - int i; - - if (qtbl == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); - - prec = 0; - for (i = 0; i < DCTSIZE2; i++) { - if (qtbl->quantval[i] > 255) - prec = 1; - } - - if (! qtbl->sent_table) { - emit_marker(cinfo, M_DQT); - - emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); - - emit_byte(cinfo, index + (prec<<4)); - - for (i = 0; i < DCTSIZE2; i++) { - /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; - if (prec) - emit_byte(cinfo, (int) (qval >> 8)); - emit_byte(cinfo, (int) (qval & 0xFF)); - } - - qtbl->sent_table = TRUE; - } - - return prec; -} - - -LOCAL(void) -emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) -/* Emit a DHT marker */ -{ - JHUFF_TBL * htbl; - int length, i; - - if (is_ac) { - htbl = cinfo->ac_huff_tbl_ptrs[index]; - index += 0x10; /* output index has AC bit set */ - } else { - htbl = cinfo->dc_huff_tbl_ptrs[index]; - } - - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); - - if (! htbl->sent_table) { - emit_marker(cinfo, M_DHT); - - length = 0; - for (i = 1; i <= 16; i++) - length += htbl->bits[i]; - - emit_2bytes(cinfo, length + 2 + 1 + 16); - emit_byte(cinfo, index); - - for (i = 1; i <= 16; i++) - emit_byte(cinfo, htbl->bits[i]); - - for (i = 0; i < length; i++) - emit_byte(cinfo, htbl->huffval[i]); - - htbl->sent_table = TRUE; - } -} - - -LOCAL(void) -emit_dac (j_compress_ptr cinfo) -/* Emit a DAC marker */ -/* Since the useful info is so small, we want to emit all the tables in */ -/* one DAC marker. Therefore this routine does its own scan of the table. */ -{ -#ifdef C_ARITH_CODING_SUPPORTED - char dc_in_use[NUM_ARITH_TBLS]; - char ac_in_use[NUM_ARITH_TBLS]; - int length, i; - jpeg_component_info *compptr; - - for (i = 0; i < NUM_ARITH_TBLS; i++) - dc_in_use[i] = ac_in_use[i] = 0; - - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - dc_in_use[compptr->dc_tbl_no] = 1; - ac_in_use[compptr->ac_tbl_no] = 1; - } - - length = 0; - for (i = 0; i < NUM_ARITH_TBLS; i++) - length += dc_in_use[i] + ac_in_use[i]; - - emit_marker(cinfo, M_DAC); - - emit_2bytes(cinfo, length*2 + 2); - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - if (dc_in_use[i]) { - emit_byte(cinfo, i); - emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); - } - if (ac_in_use[i]) { - emit_byte(cinfo, i + 0x10); - emit_byte(cinfo, cinfo->arith_ac_K[i]); - } - } -#endif /* C_ARITH_CODING_SUPPORTED */ -} - - -LOCAL(void) -emit_dri (j_compress_ptr cinfo) -/* Emit a DRI marker */ -{ - emit_marker(cinfo, M_DRI); - - emit_2bytes(cinfo, 4); /* fixed length */ - - emit_2bytes(cinfo, (int) cinfo->restart_interval); -} - - -LOCAL(void) -emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) -/* Emit a SOF marker */ -{ - int ci; - jpeg_component_info *compptr; - - emit_marker(cinfo, code); - - emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ - - /* Make sure image isn't bigger than SOF field can handle */ - if ((long) cinfo->image_height > 65535L || - (long) cinfo->image_width > 65535L) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); - - emit_byte(cinfo, cinfo->data_precision); - emit_2bytes(cinfo, (int) cinfo->image_height); - emit_2bytes(cinfo, (int) cinfo->image_width); - - emit_byte(cinfo, cinfo->num_components); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - emit_byte(cinfo, compptr->component_id); - emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); - emit_byte(cinfo, compptr->quant_tbl_no); - } -} - - -LOCAL(void) -emit_sos (j_compress_ptr cinfo) -/* Emit a SOS marker */ -{ - int i, td, ta; - jpeg_component_info *compptr; - - emit_marker(cinfo, M_SOS); - - emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ - - emit_byte(cinfo, cinfo->comps_in_scan); - - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - emit_byte(cinfo, compptr->component_id); - td = compptr->dc_tbl_no; - ta = compptr->ac_tbl_no; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan; - * furthermore, Huffman coding of DC refinement uses no table at all. - * We emit 0 for unused field(s); this is recommended by the P&M text - * but does not seem to be specified in the standard. - */ - if (cinfo->Ss == 0) { - ta = 0; /* DC scan */ - if (cinfo->Ah != 0 && !cinfo->arith_code) - td = 0; /* no DC table either */ - } else { - td = 0; /* AC scan */ - } - } - emit_byte(cinfo, (td << 4) + ta); - } - - emit_byte(cinfo, cinfo->Ss); - emit_byte(cinfo, cinfo->Se); - emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); -} - - -LOCAL(void) -emit_jfif_app0 (j_compress_ptr cinfo) -/* Emit a JFIF-compliant APP0 marker */ -{ - /* - * Length of APP0 block (2 bytes) - * Block ID (4 bytes - ASCII "JFIF") - * Zero byte (1 byte to terminate the ID string) - * Version Major, Minor (2 bytes - major first) - * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) - * Xdpu (2 bytes - dots per unit horizontal) - * Ydpu (2 bytes - dots per unit vertical) - * Thumbnail X size (1 byte) - * Thumbnail Y size (1 byte) - */ - - emit_marker(cinfo, M_APP0); - - emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ - - emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ - emit_byte(cinfo, 0x46); - emit_byte(cinfo, 0x49); - emit_byte(cinfo, 0x46); - emit_byte(cinfo, 0); - emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ - emit_byte(cinfo, cinfo->JFIF_minor_version); - emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ - emit_2bytes(cinfo, (int) cinfo->X_density); - emit_2bytes(cinfo, (int) cinfo->Y_density); - emit_byte(cinfo, 0); /* No thumbnail image */ - emit_byte(cinfo, 0); -} - - -LOCAL(void) -emit_adobe_app14 (j_compress_ptr cinfo) -/* Emit an Adobe APP14 marker */ -{ - /* - * Length of APP14 block (2 bytes) - * Block ID (5 bytes - ASCII "Adobe") - * Version Number (2 bytes - currently 100) - * Flags0 (2 bytes - currently 0) - * Flags1 (2 bytes - currently 0) - * Color transform (1 byte) - * - * Although Adobe TN 5116 mentions Version = 101, all the Adobe files - * now in circulation seem to use Version = 100, so that's what we write. - * - * We write the color transform byte as 1 if the JPEG color space is - * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with - * whether the encoder performed a transformation, which is pretty useless. - */ - - emit_marker(cinfo, M_APP14); - - emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ - - emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ - emit_byte(cinfo, 0x64); - emit_byte(cinfo, 0x6F); - emit_byte(cinfo, 0x62); - emit_byte(cinfo, 0x65); - emit_2bytes(cinfo, 100); /* Version */ - emit_2bytes(cinfo, 0); /* Flags0 */ - emit_2bytes(cinfo, 0); /* Flags1 */ - switch (cinfo->jpeg_color_space) { - case JCS_YCbCr: - emit_byte(cinfo, 1); /* Color transform = 1 */ - break; - case JCS_YCCK: - emit_byte(cinfo, 2); /* Color transform = 2 */ - break; - default: - emit_byte(cinfo, 0); /* Color transform = 0 */ - break; - } -} - - -/* - * These routines allow writing an arbitrary marker with parameters. - * The only intended use is to emit COM or APPn markers after calling - * write_file_header and before calling write_frame_header. - * Other uses are not guaranteed to produce desirable results. - * Counting the parameter bytes properly is the caller's responsibility. - */ - -METHODDEF(void) -write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) -/* Emit an arbitrary marker header */ -{ - if (datalen > (unsigned int) 65533) /* safety check */ - ERREXIT(cinfo, JERR_BAD_LENGTH); - - emit_marker(cinfo, (JPEG_MARKER) marker); - - emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ -} - -METHODDEF(void) -write_marker_byte (j_compress_ptr cinfo, int val) -/* Emit one byte of marker parameters following write_marker_header */ -{ - emit_byte(cinfo, val); -} - - -/* - * Write datastream header. - * This consists of an SOI and optional APPn markers. - * We recommend use of the JFIF marker, but not the Adobe marker, - * when using YCbCr or grayscale data. The JFIF marker should NOT - * be used for any other JPEG colorspace. The Adobe marker is helpful - * to distinguish RGB, CMYK, and YCCK colorspaces. - * Note that an application can write additional header markers after - * jpeg_start_compress returns. - */ - -METHODDEF(void) -write_file_header (j_compress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - emit_marker(cinfo, M_SOI); /* first the SOI */ - - /* SOI is defined to reset restart interval to 0 */ - marker->last_restart_interval = 0; - - if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ - emit_jfif_app0(cinfo); - if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ - emit_adobe_app14(cinfo); -} - - -/* - * Write frame header. - * This consists of DQT and SOFn markers. - * Note that we do not emit the SOF until we have emitted the DQT(s). - * This avoids compatibility problems with incorrect implementations that - * try to error-check the quant table numbers as soon as they see the SOF. - */ - -METHODDEF(void) -write_frame_header (j_compress_ptr cinfo) -{ - int ci, prec; - boolean is_baseline; - jpeg_component_info *compptr; - - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ - prec = 0; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); - } - /* now prec is nonzero iff there are any 16-bit quant tables. */ - - /* Check for a non-baseline specification. - * Note we assume that Huffman table numbers won't be changed later. - */ - if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { - is_baseline = FALSE; - } else { - is_baseline = TRUE; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) - is_baseline = FALSE; - } - if (prec && is_baseline) { - is_baseline = FALSE; - /* If it's baseline except for quantizer size, warn the user */ - TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); - } - } - - /* Emit the proper SOF marker */ - if (cinfo->arith_code) { - emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ - } else { - if (cinfo->progressive_mode) - emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ - else if (is_baseline) - emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ - else - emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ - } -} - - -/* - * Write scan header. - * This consists of DHT or DAC markers, optional DRI, and SOS. - * Compressed data will be written following the SOS. - */ - -METHODDEF(void) -write_scan_header (j_compress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - int i; - jpeg_component_info *compptr; - - if (cinfo->arith_code) { - /* Emit arith conditioning info. We may have some duplication - * if the file has multiple scans, but it's so small it's hardly - * worth worrying about. - */ - emit_dac(cinfo); - } else { - /* Emit Huffman tables. - * Note that emit_dht() suppresses any duplicate tables. - */ - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan */ - if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - } else { - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } else { - /* Sequential mode: need both DC and AC tables */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } - } - - /* Emit DRI if required --- note that DRI value could change for each scan. - * We avoid wasting space with unnecessary DRIs, however. - */ - if (cinfo->restart_interval != marker->last_restart_interval) { - emit_dri(cinfo); - marker->last_restart_interval = cinfo->restart_interval; - } - - emit_sos(cinfo); -} - - -/* - * Write datastream trailer. - */ - -METHODDEF(void) -write_file_trailer (j_compress_ptr cinfo) -{ - emit_marker(cinfo, M_EOI); -} - - -/* - * Write an abbreviated table-specification datastream. - * This consists of SOI, DQT and DHT tables, and EOI. - * Any table that is defined and not marked sent_table = TRUE will be - * emitted. Note that all tables will be marked sent_table = TRUE at exit. - */ - -METHODDEF(void) -write_tables_only (j_compress_ptr cinfo) -{ - int i; - - emit_marker(cinfo, M_SOI); - - for (i = 0; i < NUM_QUANT_TBLS; i++) { - if (cinfo->quant_tbl_ptrs[i] != NULL) - (void) emit_dqt(cinfo, i); - } - - if (! cinfo->arith_code) { - for (i = 0; i < NUM_HUFF_TBLS; i++) { - if (cinfo->dc_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, FALSE); - if (cinfo->ac_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, TRUE); - } - } - - emit_marker(cinfo, M_EOI); -} - - -/* - * Initialize the marker writer module. - */ - -GLOBAL(void) -jinit_marker_writer (j_compress_ptr cinfo) -{ - my_marker_ptr marker; - - /* Create the subobject */ - marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_marker_writer)); - cinfo->marker = (struct jpeg_marker_writer *) marker; - /* Initialize method pointers */ - marker->pub.write_file_header = write_file_header; - marker->pub.write_frame_header = write_frame_header; - marker->pub.write_scan_header = write_scan_header; - marker->pub.write_file_trailer = write_file_trailer; - marker->pub.write_tables_only = write_tables_only; - marker->pub.write_marker_header = write_marker_header; - marker->pub.write_marker_byte = write_marker_byte; - /* Initialize private state */ - marker->last_restart_interval = 0; -} +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int index) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[index]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/Source/External/LibJPEG/jcmaster.c b/Source/External/LibJPEG/jcmaster.c index e61138b..aab4020 100644 --- a/Source/External/LibJPEG/jcmaster.c +++ b/Source/External/LibJPEG/jcmaster.c @@ -1,590 +1,590 @@ -/* - * jcmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG compressor. - * These routines are concerned with parameter validation, initial setup, - * and inter-pass control (determining the number of passes and the work - * to be done in each pass). - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ -} c_pass_type; - -typedef struct { - struct jpeg_comp_master pub; /* public fields */ - - c_pass_type pass_type; /* the type of the current pass */ - - int pass_number; /* # of passes completed */ - int total_passes; /* total # of passes needed */ - - int scan_number; /* current index in scan_info[] */ -} my_comp_master; - -typedef my_comp_master * my_master_ptr; - - -/* - * Support routines that do various essential calculations. - */ - -LOCAL(void) -initial_setup (j_compress_ptr cinfo) -/* Do computations that are needed before master selection phase */ -{ - int ci; - jpeg_component_info *compptr; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* Sanity check on image dimensions */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0 || cinfo->input_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* Width of an input scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Fill in the correct component_index value; don't rely on application */ - compptr->component_index = ci; - /* For compression, we never do DCT scaling. */ - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed (this flag isn't actually used for compression) */ - compptr->component_needed = TRUE; - } - - /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). - */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); -} - - -#ifdef C_MULTISCAN_FILES_SUPPORTED - -LOCAL(void) -validate_script (j_compress_ptr cinfo) -/* Verify that the scan script in cinfo->scan_info[] is valid; also - * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. - */ -{ - const jpeg_scan_info * scanptr; - int scanno, ncomps, ci, coefi, thisi; - int Ss, Se, Ah, Al; - boolean component_sent[MAX_COMPONENTS]; -#ifdef C_PROGRESSIVE_SUPPORTED - int * last_bitpos_ptr; - int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; - /* -1 until that coefficient has been seen; then last Al for it */ -#endif - - if (cinfo->num_scans <= 0) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); - - /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; - * for progressive JPEG, no scan can have this. - */ - scanptr = cinfo->scan_info; - if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { -#ifdef C_PROGRESSIVE_SUPPORTED - cinfo->progressive_mode = TRUE; - last_bitpos_ptr = & last_bitpos[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (coefi = 0; coefi < DCTSIZE2; coefi++) - *last_bitpos_ptr++ = -1; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - cinfo->progressive_mode = FALSE; - for (ci = 0; ci < cinfo->num_components; ci++) - component_sent[ci] = FALSE; - } - - for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { - /* Validate component indexes */ - ncomps = scanptr->comps_in_scan; - if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (thisi < 0 || thisi >= cinfo->num_components) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - /* Components must appear in SOF order within each scan */ - if (ci > 0 && thisi <= scanptr->component_index[ci-1]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - } - /* Validate progression parameters */ - Ss = scanptr->Ss; - Se = scanptr->Se; - Ah = scanptr->Ah; - Al = scanptr->Al; - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that - * seems wrong: the upper bound ought to depend on data precision. - * Perhaps they really meant 0..N+1 for N-bit precision. - * Here we allow 0..10 for 8-bit data; Al larger than 10 results in - * out-of-range reconstructed DC values during the first DC scan, - * which might cause problems for some decoders. - */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_AH_AL 10 -#else -#define MAX_AH_AL 13 -#endif - if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - if (Ss == 0) { - if (Se != 0) /* DC and AC together not OK */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { - if (ncomps != 1) /* AC scans must be for only one component */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - for (ci = 0; ci < ncomps; ci++) { - last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; - if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - for (coefi = Ss; coefi <= Se; coefi++) { - if (last_bitpos_ptr[coefi] < 0) { - /* first scan of this coefficient */ - if (Ah != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { - /* not first scan */ - if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - last_bitpos_ptr[coefi] = Al; - } - } -#endif - } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - /* Make sure components are not sent twice */ - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (component_sent[thisi]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - component_sent[thisi] = TRUE; - } - } - } - - /* Now verify that everything got sent. */ - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - /* For progressive mode, we only check that at least some DC data - * got sent for each component; the spec does not require that all bits - * of all coefficients be transmitted. Would it be wiser to enforce - * transmission of all coefficient bits?? - */ - for (ci = 0; ci < cinfo->num_components; ci++) { - if (last_bitpos[ci][0] < 0) - ERREXIT(cinfo, JERR_MISSING_DATA); - } -#endif - } else { - for (ci = 0; ci < cinfo->num_components; ci++) { - if (! component_sent[ci]) - ERREXIT(cinfo, JERR_MISSING_DATA); - } - } -} - -#endif /* C_MULTISCAN_FILES_SUPPORTED */ - - -LOCAL(void) -select_scan_parameters (j_compress_ptr cinfo) -/* Set up the scan parameters for the current scan */ -{ - int ci; - -#ifdef C_MULTISCAN_FILES_SUPPORTED - if (cinfo->scan_info != NULL) { - /* Prepare for current scan --- the script is already validated */ - my_master_ptr master = (my_master_ptr) cinfo->master; - const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; - - cinfo->comps_in_scan = scanptr->comps_in_scan; - for (ci = 0; ci < scanptr->comps_in_scan; ci++) { - cinfo->cur_comp_info[ci] = - &cinfo->comp_info[scanptr->component_index[ci]]; - } - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; - } - else -#endif - { - /* Prepare for single sequential-JPEG scan containing all components */ - if (cinfo->num_components > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPS_IN_SCAN); - cinfo->comps_in_scan = cinfo->num_components; - for (ci = 0; ci < cinfo->num_components; ci++) { - cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; - } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2-1; - cinfo->Ah = 0; - cinfo->Al = 0; - } -} - - -LOCAL(void) -per_scan_setup (j_compress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } - - /* Convert restart specified in rows to actual MCU count. */ - /* Note that count must fit in 16 bits, so we provide limiting. */ - if (cinfo->restart_in_rows > 0) { - long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; - cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); - } -} - - -/* - * Per-pass setup. - * This is called at the beginning of each pass. We determine which modules - * will be active during this pass and give them appropriate start_pass calls. - * We also set is_last_pass to indicate whether any more passes will be - * required. - */ - -METHODDEF(void) -prepare_for_pass (j_compress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - switch (master->pass_type) { - case main_pass: - /* Initial pass: will collect input data, and do either Huffman - * optimization or data output for the first scan. - */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (! cinfo->raw_data_in) { - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->downsample->start_pass) (cinfo); - (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); - } - (*cinfo->fdct->start_pass) (cinfo); - (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); - (*cinfo->coef->start_pass) (cinfo, - (master->total_passes > 1 ? - JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - if (cinfo->optimize_coding) { - /* No immediate data output; postpone writing frame/scan headers */ - master->pub.call_pass_startup = FALSE; - } else { - /* Will write frame/scan headers at first jpeg_write_scanlines call */ - master->pub.call_pass_startup = TRUE; - } - break; -#ifdef ENTROPY_OPT_SUPPORTED - case huff_opt_pass: - /* Do Huffman optimization for a scan after the first one. */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { - (*cinfo->entropy->start_pass) (cinfo, TRUE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - master->pub.call_pass_startup = FALSE; - break; - } - /* Special case: Huffman DC refinement scans need no Huffman table - * and therefore we can skip the optimization pass for them. - */ - master->pass_type = output_pass; - master->pass_number++; - /*FALLTHROUGH*/ -#endif - case output_pass: - /* Do a data-output pass. */ - /* We need not repeat per-scan setup if prior optimization pass did it. */ - if (! cinfo->optimize_coding) { - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - } - (*cinfo->entropy->start_pass) (cinfo, FALSE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - /* We emit frame/scan headers now */ - if (master->scan_number == 0) - (*cinfo->marker->write_frame_header) (cinfo); - (*cinfo->marker->write_scan_header) (cinfo); - master->pub.call_pass_startup = FALSE; - break; - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - } - - master->pub.is_last_pass = (master->pass_number == master->total_passes-1); - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->total_passes; - } -} - - -/* - * Special start-of-pass hook. - * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. - * In single-pass processing, we need this hook because we don't want to - * write frame/scan headers during jpeg_start_compress; we want to let the - * application write COM markers etc. between jpeg_start_compress and the - * jpeg_write_scanlines loop. - * In multi-pass processing, this routine is not used. - */ - -METHODDEF(void) -pass_startup (j_compress_ptr cinfo) -{ - cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ - - (*cinfo->marker->write_frame_header) (cinfo); - (*cinfo->marker->write_scan_header) (cinfo); -} - - -/* - * Finish up at end of pass. - */ - -METHODDEF(void) -finish_pass_master (j_compress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* The entropy coder always needs an end-of-pass call, - * either to analyze statistics or to flush its output buffer. - */ - (*cinfo->entropy->finish_pass) (cinfo); - - /* Update state for next pass */ - switch (master->pass_type) { - case main_pass: - /* next pass is either output of scan 0 (after optimization) - * or output of scan 1 (if no optimization). - */ - master->pass_type = output_pass; - if (! cinfo->optimize_coding) - master->scan_number++; - break; - case huff_opt_pass: - /* next pass is always output of current scan */ - master->pass_type = output_pass; - break; - case output_pass: - /* next pass is either optimization or output of next scan */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - master->scan_number++; - break; - } - - master->pass_number++; -} - - -/* - * Initialize master compression control. - */ - -GLOBAL(void) -jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *) master; - master->pub.prepare_for_pass = prepare_for_pass; - master->pub.pass_startup = pass_startup; - master->pub.finish_pass = finish_pass_master; - master->pub.is_last_pass = FALSE; - - /* Validate parameters, determine derived values */ - initial_setup(cinfo); - - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED - validate_script(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - cinfo->progressive_mode = FALSE; - cinfo->num_scans = 1; - } - - if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ - - /* Initialize my private state */ - if (transcode_only) { - /* no main pass in transcoding */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - else - master->pass_type = output_pass; - } else { - /* for normal compression, first pass is always this type: */ - master->pass_type = main_pass; - } - master->scan_number = 0; - master->pass_number = 0; - if (cinfo->optimize_coding) - master->total_passes = cinfo->num_scans * 2; - else - master->total_passes = cinfo->num_scans; -} +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do DCT scaling. */ + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } + else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = DCTSIZE; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*cinfo->entropy->finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ + cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/Source/External/LibJPEG/jcomapi.c b/Source/External/LibJPEG/jcomapi.c index 1b1a340..9b1fa75 100644 --- a/Source/External/LibJPEG/jcomapi.c +++ b/Source/External/LibJPEG/jcomapi.c @@ -1,106 +1,106 @@ -/* - * jcomapi.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface routines that are used for both - * compression and decompression. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Abort processing of a JPEG compression or decompression operation, - * but don't destroy the object itself. - * - * For this, we merely clean up all the nonpermanent memory pools. - * Note that temp files (virtual arrays) are not allowed to belong to - * the permanent pool, so we will be able to close all temp files here. - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_abort (j_common_ptr cinfo) -{ - int pool; - - /* Do nothing if called on a not-initialized or destroyed JPEG object. */ - if (cinfo->mem == NULL) - return; - - /* Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { - (*cinfo->mem->free_pool) (cinfo, pool); - } - - /* Reset overall state for possible reuse of object */ - if (cinfo->is_decompressor) { - cinfo->global_state = DSTATE_START; - /* Try to keep application from accessing now-deleted marker list. - * A bit kludgy to do it here, but this is the most central place. - */ - ((j_decompress_ptr) cinfo)->marker_list = NULL; - } else { - cinfo->global_state = CSTATE_START; - } -} - - -/* - * Destruction of a JPEG object. - * - * Everything gets deallocated except the master jpeg_compress_struct itself - * and the error manager struct. Both of these are supplied by the application - * and must be freed, if necessary, by the application. (Often they are on - * the stack and so don't need to be freed anyway.) - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_destroy (j_common_ptr cinfo) -{ - /* We need only tell the memory manager to release everything. */ - /* NB: mem pointer is NULL if memory mgr failed to initialize. */ - if (cinfo->mem != NULL) - (*cinfo->mem->self_destruct) (cinfo); - cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ - cinfo->global_state = 0; /* mark it destroyed */ -} - - -/* - * Convenience routines for allocating quantization and Huffman tables. - * (Would jutils.c be a more reasonable place to put these?) - */ - -GLOBAL(JQUANT_TBL *) -jpeg_alloc_quant_table (j_common_ptr cinfo) -{ - JQUANT_TBL *tbl; - - tbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} - - -GLOBAL(JHUFF_TBL *) -jpeg_alloc_huff_table (j_common_ptr cinfo) -{ - JHUFF_TBL *tbl; - - tbl = (JHUFF_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/Source/External/LibJPEG/jconfig.h b/Source/External/LibJPEG/jconfig.h index fbc67c3..630ab0e 100644 --- a/Source/External/LibJPEG/jconfig.h +++ b/Source/External/LibJPEG/jconfig.h @@ -1,13 +1,12 @@ -#ifdef _WIN32 // Microsoft Visual Studio - #include "jconfig.vc" - #include -#elif SN_TARGET_PS3 - #include "jconfig.ps3" - #include -#elif (linux && i386) - #include "jconfig.lnx86" - #include -#else - #include "jconfig.lnx86" - #include -#endif +#ifdef _WIN32 // Microsoft Visual Studio + #include "jconfig.vc" + #include +#elif SN_TARGET_PS3 + #include "jconfig.ps3" + #include +#elif ((linux) || (__APPLE__)) + #include "jconfig.lnx86" + #include +#else + #error "LibJPEG: Unsupported Platform!" +#endif diff --git a/Source/External/LibJPEG/jconfig.lnx86 b/Source/External/LibJPEG/jconfig.lnx86 index 1327dc9..9594ec5 100644 --- a/Source/External/LibJPEG/jconfig.lnx86 +++ b/Source/External/LibJPEG/jconfig.lnx86 @@ -1,45 +1,45 @@ -/* jconfig.h. Generated automatically by configure. */ -/* jconfig.cfg --- source file edited by configure script */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -#undef void -#undef const -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS -#undef NEED_SHORT_EXTERNAL_NAMES -/* Define this if you get warnings about undefined structures. */ -#undef INCOMPLETE_TYPES_BROKEN - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED -#define INLINE __inline__ -/* These are for configuring the JPEG memory manager. */ -#undef DEFAULT_MAX_MEM -#undef NO_MKTEMP - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#undef TWO_FILE_COMMANDLINE -#undef NEED_SIGNAL_CATCHER -#undef DONT_USE_B_MODE - -/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ -#undef PROGRESS_REPORT - -#endif /* JPEG_CJPEG_DJPEG */ +/* jconfig.h. Generated automatically by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#define INLINE __inline__ +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Source/External/LibJPEG/jconfig.ps3 b/Source/External/LibJPEG/jconfig.ps3 index da52205..fb70e52 100644 --- a/Source/External/LibJPEG/jconfig.ps3 +++ b/Source/External/LibJPEG/jconfig.ps3 @@ -1,45 +1,45 @@ -/* jconfig.mac --- jconfig.h for CodeWarrior on Apple Macintosh */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -//#define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */ - -#define ALIGN_TYPE long /* Needed for 680x0 Macs */ - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#define USE_CCOMMAND /* Command line reader for Macintosh */ -#define TWO_FILE_COMMANDLINE /* Binary I/O thru stdin/stdout doesn't work */ - -#undef NEED_SIGNAL_CATCHER -#undef DONT_USE_B_MODE -#undef PROGRESS_REPORT /* optional */ - -#define NO_GETENV 1 - -#endif /* JPEG_CJPEG_DJPEG */ +/* jconfig.mac --- jconfig.h for CodeWarrior on Apple Macintosh */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +//#define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */ + +#define ALIGN_TYPE long /* Needed for 680x0 Macs */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define USE_CCOMMAND /* Command line reader for Macintosh */ +#define TWO_FILE_COMMANDLINE /* Binary I/O thru stdin/stdout doesn't work */ + +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#define NO_GETENV 1 + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Source/External/LibJPEG/jconfig.vc b/Source/External/LibJPEG/jconfig.vc index da1e783..d0e49da 100644 --- a/Source/External/LibJPEG/jconfig.vc +++ b/Source/External/LibJPEG/jconfig.vc @@ -1,47 +1,47 @@ -/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ -/* see jconfig.doc for explanations */ - -#define _CRT_SECURE_NO_DEPRECATE 1 // Undeprecate CRT functions - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -/* Define "boolean" as unsigned char, not int, per Windows custom */ -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#define TWO_FILE_COMMANDLINE /* optional */ -#define USE_SETMODE /* Microsoft has setmode() */ -#undef NEED_SIGNAL_CATCHER -#undef DONT_USE_B_MODE -#undef PROGRESS_REPORT /* optional */ - -#endif /* JPEG_CJPEG_DJPEG */ +/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ +/* see jconfig.doc for explanations */ + +#define _CRT_SECURE_NO_DEPRECATE 1 // Undeprecate CRT functions + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Microsoft has setmode() */ +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Source/External/LibJPEG/jcparam.c b/Source/External/LibJPEG/jcparam.c index bbd175c..6fc48f5 100644 --- a/Source/External/LibJPEG/jcparam.c +++ b/Source/External/LibJPEG/jcparam.c @@ -1,610 +1,610 @@ -/* - * jcparam.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains optional default-setting code for the JPEG compressor. - * Applications do not have to use this file, but those that don't use it - * must know a lot more about the innards of the JPEG code. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Quantization table setup routines - */ - -GLOBAL(void) -jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, boolean force_baseline) -/* Define a quantization table equal to the basic_table times - * a scale factor (given as a percentage). - * If force_baseline is TRUE, the computed quantization table entries - * are limited to 1..255 for JPEG baseline compatibility. - */ -{ - JQUANT_TBL ** qtblptr; - int i; - long temp; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); - - qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; - - if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); - - for (i = 0; i < DCTSIZE2; i++) { - temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; - /* limit the values to the valid range */ - if (temp <= 0L) temp = 1L; - if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ - if (force_baseline && temp > 255L) - temp = 255L; /* limit to baseline range if requested */ - (*qtblptr)->quantval[i] = (UINT16) temp; - } - - /* Initialize sent_table FALSE so table will be written to JPEG file. */ - (*qtblptr)->sent_table = FALSE; -} - - -GLOBAL(void) -jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, - boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables - * and a straight percentage-scaling quality scale. In most cases it's better - * to use jpeg_set_quality (below); this entry point is provided for - * applications that insist on a linear percentage scaling. - */ -{ - /* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ - static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 - }; - static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - }; - - /* Set up two quantization tables using the specified scaling */ - jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, - scale_factor, force_baseline); - jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, - scale_factor, force_baseline); -} - - -GLOBAL(int) -jpeg_quality_scaling (int quality) -/* Convert a user-specified quality rating to a percentage scaling factor - * for an underlying quantization table, using our recommended scaling curve. - * The input 'quality' factor should be 0 (terrible) to 100 (very good). - */ -{ - /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ - if (quality <= 0) quality = 1; - if (quality > 100) quality = 100; - - /* The basic table is used as-is (scaling 100) for a quality of 50. - * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; - * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table - * to make all the table entries 1 (hence, minimum quantization loss). - * Qualities 1..50 are converted to scaling percentage 5000/Q. - */ - if (quality < 50) - quality = 5000 / quality; - else - quality = 200 - quality*2; - - return quality; -} - - -GLOBAL(void) -jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables. - * This is the standard quality-adjusting entry point for typical user - * interfaces; only those who want detailed control over quantization tables - * would use the preceding three routines directly. - */ -{ - /* Convert user 0-100 rating to percentage scaling */ - quality = jpeg_quality_scaling(quality); - - /* Set up standard quality tables */ - jpeg_set_linear_quality(cinfo, quality, force_baseline); -} - - -/* - * Huffman table setup routines - */ - -LOCAL(void) -add_huff_table (j_compress_ptr cinfo, - JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) -/* Define a Huffman table */ -{ - int nsymbols, len; - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - /* Copy the number-of-symbols-of-each-code-length counts */ - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - - /* Validate the counts. We do this here mainly so we can copy the right - * number of symbols from the val[] array, without risking marching off - * the end of memory. jchuff.c will do a more thorough test later. - */ - nsymbols = 0; - for (len = 1; len <= 16; len++) - nsymbols += bits[len]; - if (nsymbols < 1 || nsymbols > 256) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - - MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); - - /* Initialize sent_table FALSE so table will be written to JPEG file. */ - (*htblptr)->sent_table = FALSE; -} - - -LOCAL(void) -std_huff_tables (j_compress_ptr cinfo) -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -{ - static const UINT8 bits_dc_luminance[17] = - { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; - static const UINT8 val_dc_luminance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - - static const UINT8 bits_dc_chrominance[17] = - { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; - static const UINT8 val_dc_chrominance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - - static const UINT8 bits_ac_luminance[17] = - { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; - static const UINT8 val_ac_luminance[] = - { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; - - static const UINT8 bits_ac_chrominance[17] = - { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - static const UINT8 val_ac_chrominance[] = - { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; - - add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], - bits_dc_luminance, val_dc_luminance); - add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], - bits_ac_luminance, val_ac_luminance); - add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], - bits_dc_chrominance, val_dc_chrominance); - add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], - bits_ac_chrominance, val_ac_chrominance); -} - - -/* - * Default parameter setup for compression. - * - * Applications that don't choose to use this routine must do their - * own setup of all these parameters. Alternately, you can call this - * to establish defaults and then alter parameters selectively. This - * is the recommended approach since, if we add any new parameters, - * your code will still work (they'll be set to reasonable defaults). - */ - -GLOBAL(void) -jpeg_set_defaults (j_compress_ptr cinfo) -{ - int i; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* Allocate comp_info array large enough for maximum component count. - * Array is made permanent in case application wants to compress - * multiple images at same param settings. - */ - if (cinfo->comp_info == NULL) - cinfo->comp_info = (jpeg_component_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - MAX_COMPONENTS * SIZEOF(jpeg_component_info)); - - /* Initialize everything not dependent on the color space */ - - cinfo->data_precision = BITS_IN_JSAMPLE; - /* Set up two quantization tables using default quality of 75 */ - jpeg_set_quality(cinfo, 75, TRUE); - /* Set up two Huffman tables */ - std_huff_tables(cinfo); - - /* Initialize default arithmetic coding conditioning */ - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - - /* Default is no multiple-scan output */ - cinfo->scan_info = NULL; - cinfo->num_scans = 0; - - /* Expect normal source image, not raw downsampled data */ - cinfo->raw_data_in = FALSE; - - /* Use Huffman coding, not arithmetic coding, by default */ - cinfo->arith_code = FALSE; - - /* By default, don't do extra passes to optimize entropy coding */ - cinfo->optimize_coding = FALSE; - /* The standard Huffman tables are only valid for 8-bit data precision. - * If the precision is higher, force optimization on so that usable - * tables will be computed. This test can be removed if default tables - * are supplied that are valid for the desired precision. - */ - if (cinfo->data_precision > 8) - cinfo->optimize_coding = TRUE; - - /* By default, use the simpler non-cosited sampling alignment */ - cinfo->CCIR601_sampling = FALSE; - - /* No input smoothing */ - cinfo->smoothing_factor = 0; - - /* DCT algorithm preference */ - cinfo->dct_method = JDCT_DEFAULT; - - /* No restart markers */ - cinfo->restart_interval = 0; - cinfo->restart_in_rows = 0; - - /* Fill in default JFIF marker parameters. Note that whether the marker - * will actually be written is determined by jpeg_set_colorspace. - * - * By default, the library emits JFIF version code 1.01. - * An application that wants to emit JFIF 1.02 extension markers should set - * JFIF_minor_version to 2. We could probably get away with just defaulting - * to 1.02, but there may still be some decoders in use that will complain - * about that; saying 1.01 should minimize compatibility problems. - */ - cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ - cinfo->JFIF_minor_version = 1; - cinfo->density_unit = 0; /* Pixel size is unknown by default */ - cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ - cinfo->Y_density = 1; - - /* Choose JPEG colorspace based on input space, set defaults accordingly */ - - jpeg_default_colorspace(cinfo); -} - - -/* - * Select an appropriate JPEG colorspace for in_color_space. - */ - -GLOBAL(void) -jpeg_default_colorspace (j_compress_ptr cinfo) -{ - switch (cinfo->in_color_space) { - case JCS_GRAYSCALE: - jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); - break; - case JCS_RGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_YCbCr: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_CMYK: - jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ - break; - case JCS_YCCK: - jpeg_set_colorspace(cinfo, JCS_YCCK); - break; - case JCS_UNKNOWN: - jpeg_set_colorspace(cinfo, JCS_UNKNOWN); - break; - default: - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - } -} - - -/* - * Set the JPEG colorspace, and choose colorspace-dependent default values. - */ - -GLOBAL(void) -jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) -{ - jpeg_component_info * compptr; - int ci; - -#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ - (compptr = &cinfo->comp_info[index], \ - compptr->component_id = (id), \ - compptr->h_samp_factor = (hsamp), \ - compptr->v_samp_factor = (vsamp), \ - compptr->quant_tbl_no = (quant), \ - compptr->dc_tbl_no = (dctbl), \ - compptr->ac_tbl_no = (actbl) ) - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* For all colorspaces, we use Q and Huff tables 0 for luminance components, - * tables 1 for chrominance components. - */ - - cinfo->jpeg_color_space = colorspace; - - cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ - cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ - - switch (colorspace) { - case JCS_GRAYSCALE: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 1; - /* JFIF specifies component ID 1 */ - SET_COMP(0, 1, 1,1, 0, 0,0); - break; - case JCS_RGB: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ - cinfo->num_components = 3; - SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); - SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); - SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); - break; - case JCS_YCbCr: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 3; - /* JFIF specifies component IDs 1,2,3 */ - /* We default to 2x2 subsamples of chrominance */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - break; - case JCS_CMYK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ - cinfo->num_components = 4; - SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); - SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); - SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); - SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); - break; - case JCS_YCCK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ - cinfo->num_components = 4; - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 2,2, 0, 0,0); - break; - case JCS_UNKNOWN: - cinfo->num_components = cinfo->input_components; - if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - for (ci = 0; ci < cinfo->num_components; ci++) { - SET_COMP(ci, ci, 1,1, 0, 0,0); - } - break; - default: - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - } -} - - -#ifdef C_PROGRESSIVE_SUPPORTED - -LOCAL(jpeg_scan_info *) -fill_a_scan (jpeg_scan_info * scanptr, int ci, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for specified component */ -{ - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - return scanptr; -} - -LOCAL(jpeg_scan_info *) -fill_scans (jpeg_scan_info * scanptr, int ncomps, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for each component */ -{ - int ci; - - for (ci = 0; ci < ncomps; ci++) { - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - } - return scanptr; -} - -LOCAL(jpeg_scan_info *) -fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) -/* Support routine: generate interleaved DC scan if possible, else N scans */ -{ - int ci; - - if (ncomps <= MAX_COMPS_IN_SCAN) { - /* Single interleaved DC scan */ - scanptr->comps_in_scan = ncomps; - for (ci = 0; ci < ncomps; ci++) - scanptr->component_index[ci] = ci; - scanptr->Ss = scanptr->Se = 0; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - } else { - /* Noninterleaved DC scan for each component */ - scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); - } - return scanptr; -} - - -/* - * Create a recommended progressive-JPEG script. - * cinfo->num_components and cinfo->jpeg_color_space must be correct. - */ - -GLOBAL(void) -jpeg_simple_progression (j_compress_ptr cinfo) -{ - int ncomps = cinfo->num_components; - int nscans; - jpeg_scan_info * scanptr; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* Figure space needed for script. Calculation must match code below! */ - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - nscans = 10; - } else { - /* All-purpose script for other color spaces. */ - if (ncomps > MAX_COMPS_IN_SCAN) - nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ - else - nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ - } - - /* Allocate space for script. - * We need to put it in the permanent pool in case the application performs - * multiple compressions without changing the settings. To avoid a memory - * leak if jpeg_simple_progression is called repeatedly for the same JPEG - * object, we try to re-use previously allocated space, and we allocate - * enough space to handle YCbCr even if initially asked for grayscale. - */ - if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { - cinfo->script_space_size = MAX(nscans, 10); - cinfo->script_space = (jpeg_scan_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - cinfo->script_space_size * SIZEOF(jpeg_scan_info)); - } - scanptr = cinfo->script_space; - cinfo->scan_info = scanptr; - cinfo->num_scans = nscans; - - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - /* Initial DC scan */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - /* Initial AC scan: get some luma data out in a hurry */ - scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); - /* Chroma data is too small to be worth expending many scans on */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); - /* Complete spectral selection for luma AC */ - scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); - /* Refine next bit of luma AC */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); - /* Finish DC successive approximation */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - /* Finish AC successive approximation */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); - /* Luma bottom bit comes last since it's usually largest scan */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); - } else { - /* All-purpose script for other color spaces. */ - /* Successive approximation first pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); - scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); - /* Successive approximation second pass */ - scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); - /* Successive approximation final pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); - } -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/Source/External/LibJPEG/jcphuff.c b/Source/External/LibJPEG/jcphuff.c index a4ee850..07f9178 100644 --- a/Source/External/LibJPEG/jcphuff.c +++ b/Source/External/LibJPEG/jcphuff.c @@ -1,833 +1,833 @@ -/* - * jcphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for progressive JPEG. - * - * We do not support output suspension in this module, since the library - * currently does not allow multiple-scan files to be written with output - * suspension. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jchuff.c */ - -#ifdef C_PROGRESSIVE_SUPPORTED - -/* Expanded entropy encoder object for progressive Huffman encoding. */ - -typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ - - /* Mode flag: TRUE for optimization, FALSE for actual data output */ - boolean gather_statistics; - - /* Bit-level coding status. - * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. - */ - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ - - /* Coding status for DC components */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - - /* Coding status for AC components */ - int ac_tbl_no; /* the table number of the single component */ - unsigned int EOBRUN; /* run length of EOBs */ - unsigned int BE; /* # of buffered correction bits before MCU */ - char * bit_buffer; /* buffer for correction bits (1 per char) */ - /* packing correction bits tightly would save some space but cost time... */ - - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan). - * Since any one scan codes only DC or only AC, we only need one set - * of tables, not one for DC and one for AC. - */ - c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Statistics tables for optimization; again, one set is enough */ - long * count_ptrs[NUM_HUFF_TBLS]; -} phuff_entropy_encoder; - -typedef phuff_entropy_encoder * phuff_entropy_ptr; - -/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit - * buffer can hold. Larger sizes may slightly improve compression, but - * 1000 is already well into the realm of overkill. - * The minimum safe size is 64 bits. - */ - -#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ - -/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. - * We assume that int right shift is unsigned if INT32 right shift is, - * which should be safe. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS int ishift_temp; -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); -METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); - - -/* - * Initialize for a Huffman-compressed scan using progressive JPEG. - */ - -METHODDEF(void) -start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - - entropy->cinfo = cinfo; - entropy->gather_statistics = gather_statistics; - - is_DC_band = (cinfo->Ss == 0); - - /* We assume jcmaster.c already validated the scan parameters. */ - - /* Select execution routines */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_first; - else - entropy->pub.encode_mcu = encode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_refine; - else { - entropy->pub.encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) - entropy->bit_buffer = (char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); - } - } - if (gather_statistics) - entropy->pub.finish_pass = finish_pass_gather_phuff; - else - entropy->pub.finish_pass = finish_pass_phuff; - - /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 - * for AC coefficients. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - /* Get table index */ - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; - } - if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[tbl] == NULL) - entropy->count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - /* Compute derived values for Huffman table */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, - & entropy->derived_tbls[tbl]); - } - } - - /* Initialize AC stuff */ - entropy->EOBRUN = 0; - entropy->BE = 0; - - /* Initialize bit buffer to empty */ - entropy->put_buffer = 0; - entropy->put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file. - * NB: these must be called only when actually outputting, - * that is, entropy->gather_statistics == FALSE. - */ - -/* Emit a byte */ -#define emit_byte(entropy,val) \ - { *(entropy)->next_output_byte++ = (JOCTET) (val); \ - if (--(entropy)->free_in_buffer == 0) \ - dump_buffer(entropy); } - - -LOCAL(void) -dump_buffer (phuff_entropy_ptr entropy) -/* Empty the output buffer; we do not support suspension in this module. */ -{ - struct jpeg_destination_mgr * dest = entropy->cinfo->dest; - - if (! (*dest->empty_output_buffer) (entropy->cinfo)) - ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); - /* After a successful buffer dump, must reset buffer pointers */ - entropy->next_output_byte = dest->next_output_byte; - entropy->free_in_buffer = dest->free_in_buffer; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(void) -emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) -/* Emit some bits, unless we are in gather mode */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = entropy->put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - if (entropy->gather_statistics) - return; /* do nothing if we're only getting stats */ - - put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(entropy, c); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(entropy, 0); - } - put_buffer <<= 8; - put_bits -= 8; - } - - entropy->put_buffer = put_buffer; /* update variables */ - entropy->put_bits = put_bits; -} - - -LOCAL(void) -flush_bits (phuff_entropy_ptr entropy) -{ - emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ - entropy->put_buffer = 0; /* and reset bit-buffer to empty */ - entropy->put_bits = 0; -} - - -/* - * Emit (or just count) a Huffman symbol. - */ - -INLINE -LOCAL(void) -emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; - emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); - } -} - - -/* - * Emit bits from a correction bit buffer. - */ - -LOCAL(void) -emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) -{ - if (entropy->gather_statistics) - return; /* no real work */ - - while (nbits > 0) { - emit_bits(entropy, (unsigned int) (*bufstart), 1); - bufstart++; - nbits--; - } -} - - -/* - * Emit any pending EOBRUN symbol. - */ - -LOCAL(void) -emit_eobrun (phuff_entropy_ptr entropy) -{ - register int temp, nbits; - - if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ - temp = entropy->EOBRUN; - nbits = 0; - while ((temp >>= 1)) - nbits++; - /* safety check: shouldn't happen given limited correction-bit buffer */ - if (nbits > 14) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); - if (nbits) - emit_bits(entropy, entropy->EOBRUN, nbits); - - entropy->EOBRUN = 0; - - /* Emit any buffered correction bits */ - emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); - entropy->BE = 0; - } -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(void) -emit_restart (phuff_entropy_ptr entropy, int restart_num) -{ - int ci; - - emit_eobrun(entropy); - - if (! entropy->gather_statistics) { - flush_bits(entropy); - emit_byte(entropy, 0xFF); - emit_byte(entropy, JPEG_RST0 + restart_num); - } - - if (entropy->cinfo->Ss == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) - entropy->last_dc_val[ci] = 0; - } else { - /* Re-initialize all AC-related fields to 0 */ - entropy->EOBRUN = 0; - entropy->BE = 0; - } -} - - -/* - * MCU encoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - int blkn, ci; - int Al = cinfo->Al; - JBLOCKROW block; - jpeg_component_info * compptr; - ISHIFT_TEMPS - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - - /* Compute the DC value after the required point transform by Al. - * This is simply an arithmetic right shift. - */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); - - /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->last_dc_val[ci]; - entropy->last_dc_val[ci] = temp2; - - /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_symbol(entropy, compptr->dc_tbl_no, nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - emit_bits(entropy, (unsigned int) temp2, nbits); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - register int r, k; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - - r = 0; /* r = run length of zeros */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { - r++; - continue; - } - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value; so the code is - * interwoven with finding the abs value (temp) and output bits (temp2). - */ - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ - temp2 = ~temp; - } else { - temp >>= Al; /* apply the point transform */ - temp2 = temp; - } - /* Watch out for case that nonzero coef is zero after point transform */ - if (temp == 0) { - r++; - continue; - } - - /* Emit any pending EOBRUN */ - if (entropy->EOBRUN > 0) - emit_eobrun(entropy); - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - emit_bits(entropy, (unsigned int) temp2, nbits); - - r = 0; /* reset zero run length */ - } - - if (r > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - if (entropy->EOBRUN == 0x7FFF) - emit_eobrun(entropy); /* force it out to avoid overflow */ - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - int blkn; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits(entropy, (unsigned int) (temp >> Al), 1); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - register int r, k; - int EOB; - char *BR_buffer; - unsigned int BR; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - int absvalues[DCTSIZE2]; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* It is convenient to make a pre-pass to determine the transformed - * coefficients' absolute values and the EOB position. - */ - EOB = 0; - for (k = cinfo->Ss; k <= Se; k++) { - temp = (*block)[jpeg_natural_order[k]]; - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value. - */ - if (temp < 0) - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - absvalues[k] = temp; /* save abs value for main pass */ - if (temp == 1) - EOB = k; /* EOB = index of last newly-nonzero coef */ - } - - /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - - r = 0; /* r = run length of zeros */ - BR = 0; /* BR = count of buffered bits added now */ - BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = absvalues[k]) == 0) { - r++; - continue; - } - - /* Emit any required ZRLs, but not if they can be folded into EOB */ - while (r > 15 && k <= EOB) { - /* emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - /* Emit ZRL */ - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - /* Emit buffered correction bits that must be associated with ZRL */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - } - - /* If the coef was previously nonzero, it only needs a correction bit. - * NOTE: a straight translation of the spec's figure G.7 would suggest - * that we also need to test r > 15. But if r > 15, we can only get here - * if k > EOB, which implies that this coefficient is not 1. - */ - if (temp > 1) { - /* The correction bit is the next bit of the absolute value. */ - BR_buffer[BR++] = (char) (temp & 1); - continue; - } - - /* Emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; - emit_bits(entropy, (unsigned int) temp, 1); - - /* Emit buffered correction bits that must be associated with this code */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - r = 0; /* reset zero run length */ - } - - if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - entropy->BE += BR; /* concat my correction bits to older ones */ - /* We force out the EOB if we risk either: - * 1. overflow of the EOB counter; - * 2. overflow of the correction bit buffer during the next MCU. - */ - if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) - emit_eobrun(entropy); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed progressive scan. - */ - -METHODDEF(void) -finish_pass_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Flush out any buffered data */ - emit_eobrun(entropy); - flush_bits(entropy); - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did[NUM_HUFF_TBLS]; - - /* Flush out buffered data (all we care about is counting the EOB symbol) */ - emit_eobrun(entropy); - - is_DC_band = (cinfo->Ss == 0); - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did, SIZEOF(did)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - tbl = compptr->ac_tbl_no; - } - if (! did[tbl]) { - if (is_DC_band) - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - else - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); - did[tbl] = TRUE; - } - } -} - - -/* - * Module initialization routine for progressive Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_phuff_encoder (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_phuff; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - entropy->count_ptrs[i] = NULL; - } - entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ +/* + * jcphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jchuff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather_phuff; + else + entropy->pub.finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_phuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/Source/External/LibJPEG/jcprepct.c b/Source/External/LibJPEG/jcprepct.c index fdc4bc2..fa93333 100644 --- a/Source/External/LibJPEG/jcprepct.c +++ b/Source/External/LibJPEG/jcprepct.c @@ -1,354 +1,354 @@ -/* - * jcprepct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the compression preprocessing controller. - * This controller manages the color conversion, downsampling, - * and edge expansion steps. - * - * Most of the complexity here is associated with buffering input rows - * as required by the downsampler. See the comments at the head of - * jcsample.c for the downsampler's needs. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* At present, jcsample.c can request context rows only for smoothing. - * In the future, we might also need context rows for CCIR601 sampling - * or other more-complex downsampling procedures. The code to support - * context rows should be compiled only if needed. - */ -#ifdef INPUT_SMOOTHING_SUPPORTED -#define CONTEXT_ROWS_SUPPORTED -#endif - - -/* - * For the simple (no-context-row) case, we just need to buffer one - * row group's worth of pixels for the downsampling step. At the bottom of - * the image, we pad to a full row group by replicating the last pixel row. - * The downsampler's last output row is then replicated if needed to pad - * out to a full iMCU row. - * - * When providing context rows, we must buffer three row groups' worth of - * pixels. Three row groups are physically allocated, but the row pointer - * arrays are made five row groups high, with the extra pointers above and - * below "wrapping around" to point to the last and first real row groups. - * This allows the downsampler to access the proper context rows. - * At the top and bottom of the image, we create dummy context rows by - * copying the first or last real pixel row. This copying could be avoided - * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the - * trouble on the compression side. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_prep_controller pub; /* public fields */ - - /* Downsampling input buffer. This buffer holds color-converted data - * until we have enough to do a downsample step. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - JDIMENSION rows_to_go; /* counts rows remaining in source image */ - int next_buf_row; /* index of next row to store in color_buf */ - -#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ - int this_row_group; /* starting row index of group to process */ - int next_buf_stop; /* downsample when we reach this index */ -#endif -} my_prep_controller; - -typedef my_prep_controller * my_prep_ptr; - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - - if (pass_mode != JBUF_PASS_THRU) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Initialize total-height counter for detecting bottom of image */ - prep->rows_to_go = cinfo->image_height; - /* Mark the conversion buffer empty */ - prep->next_buf_row = 0; -#ifdef CONTEXT_ROWS_SUPPORTED - /* Preset additional state variables for context mode. - * These aren't used in non-context mode, so we needn't test which mode. - */ - prep->this_row_group = 0; - /* Set next_buf_stop to stop after two row groups have been read in. */ - prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; -#endif -} - - -/* - * Expand an image vertically from height input_rows to height output_rows, - * by duplicating the bottom row. - */ - -LOCAL(void) -expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, - int input_rows, int output_rows) -{ - register int row; - - for (row = input_rows; row < output_rows; row++) { - jcopy_sample_rows(image_data, input_rows-1, image_data, row, - 1, num_cols); - } -} - - -/* - * Process some data in the simple no-context case. - * - * Preprocessor output data is counted in "row groups". A row group - * is defined to be v_samp_factor sample rows of each component. - * Downsampling will produce this much data from each max_v_samp_factor - * input rows. - */ - -METHODDEF(void) -pre_process_data (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int numrows, ci; - JDIMENSION inrows; - jpeg_component_info * compptr; - - while (*in_row_ctr < in_rows_avail && - *out_row_group_ctr < out_row_groups_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = cinfo->max_v_samp_factor - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - /* If at bottom of image, pad to fill the conversion buffer. */ - if (prep->rows_to_go == 0 && - prep->next_buf_row < cinfo->max_v_samp_factor) { - for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, cinfo->max_v_samp_factor); - } - prep->next_buf_row = cinfo->max_v_samp_factor; - } - /* If we've filled the conversion buffer, empty it. */ - if (prep->next_buf_row == cinfo->max_v_samp_factor) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, (JDIMENSION) 0, - output_buf, *out_row_group_ctr); - prep->next_buf_row = 0; - (*out_row_group_ctr)++; - } - /* If at bottom of image, pad the output to a full iMCU height. - * Note we assume the caller is providing a one-iMCU-height output buffer! - */ - if (prep->rows_to_go == 0 && - *out_row_group_ctr < out_row_groups_avail) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - expand_bottom_edge(output_buf[ci], - compptr->width_in_blocks * DCTSIZE, - (int) (*out_row_group_ctr * compptr->v_samp_factor), - (int) (out_row_groups_avail * compptr->v_samp_factor)); - } - *out_row_group_ctr = out_row_groups_avail; - break; /* can exit outer loop without test */ - } - } -} - - -#ifdef CONTEXT_ROWS_SUPPORTED - -/* - * Process some data in the context case. - */ - -METHODDEF(void) -pre_process_context (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int numrows, ci; - int buf_height = cinfo->max_v_samp_factor * 3; - JDIMENSION inrows; - - while (*out_row_group_ctr < out_row_groups_avail) { - if (*in_row_ctr < in_rows_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = prep->next_buf_stop - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); - /* Pad at top of image, if first time through */ - if (prep->rows_to_go == cinfo->image_height) { - for (ci = 0; ci < cinfo->num_components; ci++) { - int row; - for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, - prep->color_buf[ci], -row, - 1, cinfo->image_width); - } - } - } - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - } else { - /* Return for more data, unless we are at the bottom of the image. */ - if (prep->rows_to_go != 0) - break; - /* When at bottom of image, pad to fill the conversion buffer. */ - if (prep->next_buf_row < prep->next_buf_stop) { - for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, prep->next_buf_stop); - } - prep->next_buf_row = prep->next_buf_stop; - } - } - /* If we've gotten enough data, downsample a row group. */ - if (prep->next_buf_row == prep->next_buf_stop) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, - (JDIMENSION) prep->this_row_group, - output_buf, *out_row_group_ctr); - (*out_row_group_ctr)++; - /* Advance pointers with wraparound as necessary. */ - prep->this_row_group += cinfo->max_v_samp_factor; - if (prep->this_row_group >= buf_height) - prep->this_row_group = 0; - if (prep->next_buf_row >= buf_height) - prep->next_buf_row = 0; - prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; - } - } -} - - -/* - * Create the wrapped-around downsampling input buffer needed for context mode. - */ - -LOCAL(void) -create_context_buffer (j_compress_ptr cinfo) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int rgroup_height = cinfo->max_v_samp_factor; - int ci, i; - jpeg_component_info * compptr; - JSAMPARRAY true_buffer, fake_buffer; - - /* Grab enough space for fake row pointers for all the components; - * we need five row groups' worth of pointers for each component. - */ - fake_buffer = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (cinfo->num_components * 5 * rgroup_height) * - SIZEOF(JSAMPROW)); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate the actual buffer space (3 row groups) for this component. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ - true_buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) (3 * rgroup_height)); - /* Copy true buffer row pointers into the middle of the fake row array */ - MEMCOPY(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * SIZEOF(JSAMPROW)); - /* Fill in the above and below wraparound pointers */ - for (i = 0; i < rgroup_height; i++) { - fake_buffer[i] = true_buffer[2 * rgroup_height + i]; - fake_buffer[4 * rgroup_height + i] = true_buffer[i]; - } - prep->color_buf[ci] = fake_buffer + rgroup_height; - fake_buffer += 5 * rgroup_height; /* point to space for next component */ - } -} - -#endif /* CONTEXT_ROWS_SUPPORTED */ - - -/* - * Initialize preprocessing controller. - */ - -GLOBAL(void) -jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_prep_ptr prep; - int ci; - jpeg_component_info * compptr; - - if (need_full_buffer) /* safety check */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - prep = (my_prep_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_prep_controller)); - cinfo->prep = (struct jpeg_c_prep_controller *) prep; - prep->pub.start_pass = start_pass_prep; - - /* Allocate the color conversion buffer. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ - if (cinfo->downsample->need_context_rows) { - /* Set up to provide context rows */ -#ifdef CONTEXT_ROWS_SUPPORTED - prep->pub.pre_process_data = pre_process_context; - create_context_buffer(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* No context, just make it tall enough for one row group */ - prep->pub.pre_process_data = pre_process_data; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } - } -} +/* + * jcprepct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * DCTSIZE, + (int) (*out_row_group_ctr * compptr->v_samp_factor), + (int) (out_row_groups_avail * compptr->v_samp_factor)); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/Source/External/LibJPEG/jcsample.c b/Source/External/LibJPEG/jcsample.c index fe29fca..212ec87 100644 --- a/Source/External/LibJPEG/jcsample.c +++ b/Source/External/LibJPEG/jcsample.c @@ -1,519 +1,519 @@ -/* - * jcsample.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains downsampling routines. - * - * Downsampling input data is counted in "row groups". A row group - * is defined to be max_v_samp_factor pixel rows of each component, - * from which the downsampler produces v_samp_factor sample rows. - * A single row group is processed in each call to the downsampler module. - * - * The downsampler is responsible for edge-expansion of its output data - * to fill an integral number of DCT blocks horizontally. The source buffer - * may be modified if it is helpful for this purpose (the source buffer is - * allocated wide enough to correspond to the desired output width). - * The caller (the prep controller) is responsible for vertical padding. - * - * The downsampler may request "context rows" by setting need_context_rows - * during startup. In this case, the input arrays will contain at least - * one row group's worth of pixels above and below the passed-in data; - * the caller will create dummy rows at image top and bottom by replicating - * the first or last real pixel row. - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - * - * The downsampling algorithm used here is a simple average of the source - * pixels covered by the output pixel. The hi-falutin sampling literature - * refers to this as a "box filter". In general the characteristics of a box - * filter are not very good, but for the specific cases we normally use (1:1 - * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not - * nearly so bad. If you intend to use other sampling ratios, you'd be well - * advised to improve this code. - * - * A simple input-smoothing capability is provided. This is mainly intended - * for cleaning up color-dithered GIF input files (if you find it inadequate, - * we suggest using an external filtering program such as pnmconvol). When - * enabled, each input pixel P is replaced by a weighted sum of itself and its - * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, - * where SF = (smoothing_factor / 1024). - * Currently, smoothing is only supported for 2h2v sampling factors. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to downsample a single component */ -typedef JMETHOD(void, downsample1_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data)); - -/* Private subobject */ - -typedef struct { - struct jpeg_downsampler pub; /* public fields */ - - /* Downsampling method pointers, one per component */ - downsample1_ptr methods[MAX_COMPONENTS]; -} my_downsampler; - -typedef my_downsampler * my_downsample_ptr; - - -/* - * Initialize for a downsampling pass. - */ - -METHODDEF(void) -start_pass_downsample (j_compress_ptr cinfo) -{ - /* no work for now */ -} - - -/* - * Expand a component horizontally from width input_cols to width output_cols, - * by duplicating the rightmost samples. - */ - -LOCAL(void) -expand_right_edge (JSAMPARRAY image_data, int num_rows, - JDIMENSION input_cols, JDIMENSION output_cols) -{ - register JSAMPROW ptr; - register JSAMPLE pixval; - register int count; - int row; - int numcols = (int) (output_cols - input_cols); - - if (numcols > 0) { - for (row = 0; row < num_rows; row++) { - ptr = image_data[row] + input_cols; - pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ - for (count = numcols; count > 0; count--) - *ptr++ = pixval; - } - } -} - - -/* - * Do downsampling for a whole row group (all components). - * - * In this version we simply downsample each component independently. - */ - -METHODDEF(void) -sep_downsample (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) -{ - my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; - int ci; - jpeg_component_info * compptr; - JSAMPARRAY in_ptr, out_ptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - in_ptr = input_buf[ci] + in_row_index; - out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); - (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); - } -} - - -/* - * Downsample pixel values of a single component. - * One row group is processed per call. - * This version handles arbitrary integral sampling ratios, without smoothing. - * Note that this version is not actually used for customary sampling ratios. - */ - -METHODDEF(void) -int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; - JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - JSAMPROW inptr, outptr; - INT32 outvalue; - - h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; - v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; - numpix = h_expand * v_expand; - numpix2 = numpix/2; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * h_expand); - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - for (outcol = 0, outcol_h = 0; outcol < output_cols; - outcol++, outcol_h += h_expand) { - outvalue = 0; - for (v = 0; v < v_expand; v++) { - inptr = input_data[inrow+v] + outcol_h; - for (h = 0; h < h_expand; h++) { - outvalue += (INT32) GETJSAMPLE(*inptr++); - } - } - *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); - } - inrow += v_expand; - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * without smoothing. - */ - -METHODDEF(void) -fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - /* Copy the data */ - jcopy_sample_rows(input_data, 0, output_data, 0, - cinfo->max_v_samp_factor, cinfo->image_width); - /* Edge-expand */ - expand_right_edge(output_data, cinfo->max_v_samp_factor, - cinfo->image_width, compptr->width_in_blocks * DCTSIZE); -} - - -/* - * Downsample pixel values of a single component. - * This version handles the common case of 2:1 horizontal and 1:1 vertical, - * without smoothing. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int outrow; - JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, outptr; - register int bias; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); - - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - bias = 0; /* bias = 0,1,0,1,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) - + bias) >> 1); - bias ^= 1; /* 0=>1, 1=>0 */ - inptr += 2; - } - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * without smoothing. - */ - -METHODDEF(void) -h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow; - JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, outptr; - register int bias; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - bias = 1; /* bias = 1,2,1,2,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) - + bias) >> 2); - bias ^= 3; /* 1=>2, 2=>1 */ - inptr0 += 2; inptr1 += 2; - } - inrow += 2; - } -} - - -#ifdef INPUT_SMOOTHING_SUPPORTED - -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * with smoothing. One row of context is required. - */ - -METHODDEF(void) -h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow; - JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; - INT32 membersum, neighsum, memberscale, neighscale; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols * 2); - - /* We don't bother to form the individual "smoothed" input pixel values; - * we can directly compute the output which is the average of the four - * smoothed values. Each of the four member pixels contributes a fraction - * (1-8*SF) to its own smoothed image and a fraction SF to each of the three - * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final - * output. The four corner-adjacent neighbor pixels contribute a fraction - * SF to just one smoothed pixel, or SF/4 to the final output; while the - * eight edge-adjacent neighbors contribute SF to each of two smoothed - * pixels, or SF/2 overall. In order to use integer arithmetic, these - * factors are scaled by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ - - memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ - neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - above_ptr = input_data[inrow-1]; - below_ptr = input_data[inrow+2]; - - /* Special case for first column: pretend column -1 is same as column 0 */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); - neighsum += neighsum; - neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - - for (colctr = output_cols - 2; colctr > 0; colctr--) { - /* sum of pixels directly mapped to this output element */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - /* sum of edge-neighbor pixels */ - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); - /* The edge-neighbors count twice as much as corner-neighbors */ - neighsum += neighsum; - /* Add in the corner-neighbors */ - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); - /* form final output scaled up by 2^16 */ - membersum = membersum * memberscale + neighsum * neighscale; - /* round, descale and output it */ - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - } - - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); - neighsum += neighsum; - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); - - inrow += 2; - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * with smoothing. One row of context is required. - */ - -METHODDEF(void) -fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int outrow; - JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, above_ptr, below_ptr, outptr; - INT32 membersum, neighsum, memberscale, neighscale; - int colsum, lastcolsum, nextcolsum; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols); - - /* Each of the eight neighbor pixels contributes a fraction SF to the - * smoothed pixel, while the main pixel contributes (1-8*SF). In order - * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ - - memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ - neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ - - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - above_ptr = input_data[outrow-1]; - below_ptr = input_data[outrow+1]; - - /* Special case for first column */ - colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + - GETJSAMPLE(*inptr); - membersum = GETJSAMPLE(*inptr++); - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); - neighsum = colsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; - - for (colctr = output_cols - 2; colctr > 0; colctr--) { - membersum = GETJSAMPLE(*inptr++); - above_ptr++; below_ptr++; - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; - } - - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + colsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); - - } -} - -#endif /* INPUT_SMOOTHING_SUPPORTED */ - - -/* - * Module initialization routine for downsampling. - * Note that we must select a routine for each component. - */ - -GLOBAL(void) -jinit_downsampler (j_compress_ptr cinfo) -{ - my_downsample_ptr downsample; - int ci; - jpeg_component_info * compptr; - boolean smoothok = TRUE; - - downsample = (my_downsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_downsampler)); - cinfo->downsample = (struct jpeg_downsampler *) downsample; - downsample->pub.start_pass = start_pass_downsample; - downsample->pub.downsample = sep_downsample; - downsample->pub.need_context_rows = FALSE; - - if (cinfo->CCIR601_sampling) - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* Verify we can handle the sampling factors, and set up method pointers */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { - downsample->methods[ci] = fullsize_smooth_downsample; - downsample->pub.need_context_rows = TRUE; - } else -#endif - downsample->methods[ci] = fullsize_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { - smoothok = FALSE; - downsample->methods[ci] = h2v1_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { - downsample->methods[ci] = h2v2_smooth_downsample; - downsample->pub.need_context_rows = TRUE; - } else -#endif - downsample->methods[ci] = h2v2_downsample; - } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && - (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { - smoothok = FALSE; - downsample->methods[ci] = int_downsample; - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - } - -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor && !smoothok) - TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); -#endif -} +/* + * jcsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JSAMPROW inptr, outptr; + INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_blocks * DCTSIZE); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/Source/External/LibJPEG/jctrans.c b/Source/External/LibJPEG/jctrans.c index 8b36e36..0e6d707 100644 --- a/Source/External/LibJPEG/jctrans.c +++ b/Source/External/LibJPEG/jctrans.c @@ -1,388 +1,388 @@ -/* - * jctrans.c - * - * Copyright (C) 1995-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains library routines for transcoding compression, - * that is, writing raw DCT coefficient arrays to an output JPEG file. - * The routines in jcapimin.c will also be needed by a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(void) transencode_master_selection - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); -LOCAL(void) transencode_coef_controller - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); - - -/* - * Compression initialization for writing raw-coefficient data. - * Before calling this, all parameters and a data destination must be set up. - * Call jpeg_finish_compress() to actually write the data. - * - * The number of passed virtual arrays must match cinfo->num_components. - * Note that the virtual arrays need not be filled or even realized at - * the time write_coefficients is called; indeed, if the virtual arrays - * were requested from this compression object's memory manager, they - * typically will be realized during this routine and filled afterwards. - */ - -GLOBAL(void) -jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Mark all tables to be written */ - jpeg_suppress_tables(cinfo, FALSE); - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ - transencode_master_selection(cinfo, coef_arrays); - /* Wait for jpeg_finish_compress() call */ - cinfo->next_scanline = 0; /* so jpeg_write_marker works */ - cinfo->global_state = CSTATE_WRCOEFS; -} - - -/* - * Initialize the compression object with default parameters, - * then copy from the source object all parameters needed for lossless - * transcoding. Parameters that can be varied without loss (such as - * scan script and Huffman optimization) are left in their default states. - */ - -GLOBAL(void) -jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo) -{ - JQUANT_TBL ** qtblptr; - jpeg_component_info *incomp, *outcomp; - JQUANT_TBL *c_quant, *slot_quant; - int tblno, ci, coefi; - - /* Safety check to ensure start_compress not called yet. */ - if (dstinfo->global_state != CSTATE_START) - ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); - /* Copy fundamental image dimensions */ - dstinfo->image_width = srcinfo->image_width; - dstinfo->image_height = srcinfo->image_height; - dstinfo->input_components = srcinfo->num_components; - dstinfo->in_color_space = srcinfo->jpeg_color_space; - /* Initialize all parameters to default values */ - jpeg_set_defaults(dstinfo); - /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. - * Fix it to get the right header markers for the image colorspace. - */ - jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); - dstinfo->data_precision = srcinfo->data_precision; - dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; - /* Copy the source's quantization tables. */ - for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { - if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { - qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; - if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); - MEMCOPY((*qtblptr)->quantval, - srcinfo->quant_tbl_ptrs[tblno]->quantval, - SIZEOF((*qtblptr)->quantval)); - (*qtblptr)->sent_table = FALSE; - } - } - /* Copy the source's per-component info. - * Note we assume jpeg_set_defaults has allocated the dest comp_info array. - */ - dstinfo->num_components = srcinfo->num_components; - if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) - ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, - MAX_COMPONENTS); - for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; - ci < dstinfo->num_components; ci++, incomp++, outcomp++) { - outcomp->component_id = incomp->component_id; - outcomp->h_samp_factor = incomp->h_samp_factor; - outcomp->v_samp_factor = incomp->v_samp_factor; - outcomp->quant_tbl_no = incomp->quant_tbl_no; - /* Make sure saved quantization table for component matches the qtable - * slot. If not, the input file re-used this qtable slot. - * IJG encoder currently cannot duplicate this. - */ - tblno = outcomp->quant_tbl_no; - if (tblno < 0 || tblno >= NUM_QUANT_TBLS || - srcinfo->quant_tbl_ptrs[tblno] == NULL) - ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); - slot_quant = srcinfo->quant_tbl_ptrs[tblno]; - c_quant = incomp->quant_table; - if (c_quant != NULL) { - for (coefi = 0; coefi < DCTSIZE2; coefi++) { - if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) - ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); - } - } - /* Note: we do not copy the source's Huffman table assignments; - * instead we rely on jpeg_set_colorspace to have made a suitable choice. - */ - } - /* Also copy JFIF version and resolution information, if available. - * Strictly speaking this isn't "critical" info, but it's nearly - * always appropriate to copy it if available. In particular, - * if the application chooses to copy JFIF 1.02 extension markers from - * the source file, we need to copy the version to make sure we don't - * emit a file that has 1.02 extensions but a claimed version of 1.01. - * We will *not*, however, copy version info from mislabeled "2.01" files. - */ - if (srcinfo->saw_JFIF_marker) { - if (srcinfo->JFIF_major_version == 1) { - dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; - dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; - } - dstinfo->density_unit = srcinfo->density_unit; - dstinfo->X_density = srcinfo->X_density; - dstinfo->Y_density = srcinfo->Y_density; - } -} - - -/* - * Master selection of compression modules for transcoding. - * This substitutes for jcinit.c's initialization of the full compressor. - */ - -LOCAL(void) -transencode_master_selection (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) -{ - /* Although we don't actually use input_components for transcoding, - * jcmaster.c's initial_setup will complain if input_components is 0. - */ - cinfo->input_components = 1; - /* Initialize master control (includes parameter checking/processing) */ - jinit_c_master_control(cinfo, TRUE /* transcode only */); - - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); - } - - /* We need a special coefficient buffer controller. */ - transencode_coef_controller(cinfo, coef_arrays); - - jinit_marker_writer(cinfo); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Write the datastream header (SOI, JFIF) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ - (*cinfo->marker->write_file_header) (cinfo); -} - - -/* - * The rest of this file is a special implementation of the coefficient - * buffer controller. This is similar to jccoefct.c, but it handles only - * output from presupplied virtual arrays. Furthermore, we generate any - * dummy padding blocks on-the-fly rather than expecting them to be present - * in the arrays. - */ - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_coef_controller pub; /* public fields */ - - JDIMENSION iMCU_row_num; /* iMCU row # within image */ - JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* Virtual block array for each component. */ - jvirt_barray_ptr * whole_image; - - /* Workspace for constructing dummy blocks at right/bottom edges. */ - JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - - -LOCAL(void) -start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->mcu_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - if (pass_mode != JBUF_CRANK_DEST) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - coef->iMCU_row_num = 0; - start_iMCU_row(cinfo); -} - - -/* - * Process some data. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - -METHODDEF(boolean) -compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, blockcnt; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yindex+yoffset < compptr->last_row_height) { - /* Fill in pointers to real blocks in this row */ - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < blockcnt; xindex++) - MCU_buffer[blkn++] = buffer_ptr++; - } else { - /* At bottom of image, need a whole row of dummy blocks */ - xindex = 0; - } - /* Fill in any dummy blocks needed in this row. - * Dummy blocks are filled in the same way as in jccoefct.c: - * all zeroes in the AC entries, DC entries equal to previous - * block's DC value. The init routine has already zeroed the - * AC entries, so we need only set the DC entries correctly. - */ - for (; xindex < compptr->MCU_width; xindex++) { - MCU_buffer[blkn] = coef->dummy_buffer[blkn]; - MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; - blkn++; - } - } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - - -/* - * Initialize coefficient buffer controller. - * - * Each passed coefficient array must be the right size for that - * coefficient: width_in_blocks wide and height_in_blocks high, - * with unitheight at least v_samp_factor. - */ - -LOCAL(void) -transencode_coef_controller (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) -{ - my_coef_ptr coef; - JBLOCKROW buffer; - int i; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_c_coef_controller *) coef; - coef->pub.start_pass = start_pass_coef; - coef->pub.compress_data = compress_output; - - /* Save pointer to virtual arrays */ - coef->whole_image = coef_arrays; - - /* Allocate and pre-zero space for dummy DCT blocks. */ - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->dummy_buffer[i] = buffer + i; - } -} +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/Source/External/LibJPEG/jdapimin.c b/Source/External/LibJPEG/jdapimin.c index bd1df92..cadb59f 100644 --- a/Source/External/LibJPEG/jdapimin.c +++ b/Source/External/LibJPEG/jdapimin.c @@ -1,395 +1,395 @@ -/* - * jdapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-decompression case or the - * transcoding-only case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jdapistd.c. But also see jcomapi.c for routines - * shared by compression and decompression, and jdtrans.c for the transcoding - * case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG decompression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL(void) -jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) -{ - int i; - - /* Guard against version mismatches between library and caller. */ - cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ - if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); - if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); - - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; - } - cinfo->is_decompressor = TRUE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->src = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - /* Initialize marker processor so application can override methods - * for COM, APPn markers before calling jpeg_read_header. - */ - cinfo->marker_list = NULL; - jinit_marker_reader(cinfo); - - /* And initialize the overall input controller. */ - jinit_input_controller(cinfo); - - /* OK, I'm ready */ - cinfo->global_state = DSTATE_START; -} - - -/* - * Destruction of a JPEG decompression object - */ - -GLOBAL(void) -jpeg_destroy_decompress (j_decompress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG decompression operation, - * but don't destroy the object itself. - */ - -GLOBAL(void) -jpeg_abort_decompress (j_decompress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Set default decompression parameters. - */ - -LOCAL(void) -default_decompress_parms (j_decompress_ptr cinfo) -{ - /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ - /* Note application may override our guesses. */ - switch (cinfo->num_components) { - case 1: - cinfo->jpeg_color_space = JCS_GRAYSCALE; - cinfo->out_color_space = JCS_GRAYSCALE; - break; - - case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_RGB; - break; - case 1: - cinfo->jpeg_color_space = JCS_YCbCr; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - break; - } - } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; - - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - } - /* Always guess RGB is proper output colorspace. */ - cinfo->out_color_space = JCS_RGB; - break; - - case 4: - if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_CMYK; - break; - case 2: - cinfo->jpeg_color_space = JCS_YCCK; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ - break; - } - } else { - /* No special markers, assume straight CMYK. */ - cinfo->jpeg_color_space = JCS_CMYK; - } - cinfo->out_color_space = JCS_CMYK; - break; - - default: - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->out_color_space = JCS_UNKNOWN; - break; - } - - /* Set defaults for other decompression parameters. */ - cinfo->scale_num = 1; /* 1:1 scaling */ - cinfo->scale_denom = 1; - cinfo->output_gamma = 1.0; - cinfo->buffered_image = FALSE; - cinfo->raw_data_out = FALSE; - cinfo->dct_method = JDCT_DEFAULT; - cinfo->do_fancy_upsampling = TRUE; - cinfo->do_block_smoothing = TRUE; - cinfo->quantize_colors = FALSE; - /* We set these in case application only sets quantize_colors. */ - cinfo->dither_mode = JDITHER_FS; -#ifdef QUANT_2PASS_SUPPORTED - cinfo->two_pass_quantize = TRUE; -#else - cinfo->two_pass_quantize = FALSE; -#endif - cinfo->desired_number_of_colors = 256; - cinfo->colormap = NULL; - /* Initialize for no mode change in buffered-image mode. */ - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; -} - - -/* - * Decompression startup: read start of JPEG datastream to see what's there. - * Need only initialize JPEG object and supply a data source before calling. - * - * This routine will read as far as the first SOS marker (ie, actual start of - * compressed data), and will save all tables and parameters in the JPEG - * object. It will also initialize the decompression parameters to default - * values, and finally return JPEG_HEADER_OK. On return, the application may - * adjust the decompression parameters and then call jpeg_start_decompress. - * (Or, if the application only wanted to determine the image parameters, - * the data need not be decompressed. In that case, call jpeg_abort or - * jpeg_destroy to release any temporary space.) - * If an abbreviated (tables only) datastream is presented, the routine will - * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then - * re-use the JPEG object to read the abbreviated image datastream(s). - * It is unnecessary (but OK) to call jpeg_abort in this case. - * The JPEG_SUSPENDED return code only occurs if the data source module - * requests suspension of the decompressor. In this case the application - * should load more source data and then re-call jpeg_read_header to resume - * processing. - * If a non-suspending data source is used and require_image is TRUE, then the - * return code need not be inspected since only JPEG_HEADER_OK is possible. - * - * This routine is now just a front end to jpeg_consume_input, with some - * extra error checking. - */ - -GLOBAL(int) -jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) -{ - int retcode; - - if (cinfo->global_state != DSTATE_START && - cinfo->global_state != DSTATE_INHEADER) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - retcode = jpeg_consume_input(cinfo); - - switch (retcode) { - case JPEG_REACHED_SOS: - retcode = JPEG_HEADER_OK; - break; - case JPEG_REACHED_EOI: - if (require_image) /* Complain if application wanted an image */ - ERREXIT(cinfo, JERR_NO_IMAGE); - /* Reset to start state; it would be safer to require the application to - * call jpeg_abort, but we can't change it now for compatibility reasons. - * A side effect is to free any temporary memory (there shouldn't be any). - */ - jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ - retcode = JPEG_HEADER_TABLES_ONLY; - break; - case JPEG_SUSPENDED: - /* no work */ - break; - } - - return retcode; -} - - -/* - * Consume data in advance of what the decompressor requires. - * This can be called at any time once the decompressor object has - * been created and a data source has been set up. - * - * This routine is essentially a state machine that handles a couple - * of critical state-transition actions, namely initial setup and - * transition from header scanning to ready-for-start_decompress. - * All the actual input is done via the input controller's consume_input - * method. - */ - -GLOBAL(int) -jpeg_consume_input (j_decompress_ptr cinfo) -{ - int retcode = JPEG_SUSPENDED; - - /* NB: every possible DSTATE value should be listed in this switch */ - switch (cinfo->global_state) { - case DSTATE_START: - /* Start-of-datastream actions: reset appropriate modules */ - (*cinfo->inputctl->reset_input_controller) (cinfo); - /* Initialize application's data source module */ - (*cinfo->src->init_source) (cinfo); - cinfo->global_state = DSTATE_INHEADER; - /*FALLTHROUGH*/ - case DSTATE_INHEADER: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ - /* Set up default parameters based on header data */ - default_decompress_parms(cinfo); - /* Set global state: ready for start_decompress */ - cinfo->global_state = DSTATE_READY; - } - break; - case DSTATE_READY: - /* Can't advance past first SOS until start_decompress is called */ - retcode = JPEG_REACHED_SOS; - break; - case DSTATE_PRELOAD: - case DSTATE_PRESCAN: - case DSTATE_SCANNING: - case DSTATE_RAW_OK: - case DSTATE_BUFIMAGE: - case DSTATE_BUFPOST: - case DSTATE_STOPPING: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - break; - default: - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - return retcode; -} - - -/* - * Have we finished reading the input file? - */ - -GLOBAL(boolean) -jpeg_input_complete (j_decompress_ptr cinfo) -{ - /* Check for valid jpeg object */ - if (cinfo->global_state < DSTATE_START || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->eoi_reached; -} - - -/* - * Is there more than one scan? - */ - -GLOBAL(boolean) -jpeg_has_multiple_scans (j_decompress_ptr cinfo) -{ - /* Only valid after jpeg_read_header completes */ - if (cinfo->global_state < DSTATE_READY || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->has_multiple_scans; -} - - -/* - * Finish JPEG decompression. - * - * This will normally just verify the file trailer and release temp storage. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_decompress (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { - /* Terminate final pass of non-buffered mode */ - if (cinfo->output_scanline < cinfo->output_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state == DSTATE_BUFIMAGE) { - /* Finishing after a buffered-image operation */ - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state != DSTATE_STOPPING) { - /* STOPPING = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read until EOI */ - while (! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - /* Do final cleanup */ - (*cinfo->src->term_source) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); - return TRUE; -} +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/Source/External/LibJPEG/jdapistd.c b/Source/External/LibJPEG/jdapistd.c index f6c7fff..c8e3fa0 100644 --- a/Source/External/LibJPEG/jdapistd.c +++ b/Source/External/LibJPEG/jdapistd.c @@ -1,275 +1,275 @@ -/* - * jdapistd.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-decompression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_decompress, it will end up linking in the entire decompressor. - * We thus must separate this file from jdapimin.c to avoid linking the - * whole decompression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); - - -/* - * Decompression initialization. - * jpeg_read_header must be completed before calling this. - * - * If a multipass operating mode was selected, this will do all but the - * last pass, and thus may take a great deal of time. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_start_decompress (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize master control, select active modules */ - jinit_master_decompress(cinfo); - if (cinfo->buffered_image) { - /* No more work here; expecting jpeg_start_output next */ - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; - } - cinfo->global_state = DSTATE_PRELOAD; - } - if (cinfo->global_state == DSTATE_PRELOAD) { - /* If file has multiple scans, absorb them all into the coef buffer */ - if (cinfo->inputctl->has_multiple_scans) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return FALSE; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - } - cinfo->output_scan_number = cinfo->input_scan_number; - } else if (cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any dummy output passes, and set up for the final pass */ - return output_pass_setup(cinfo); -} - - -/* - * Set up for an output pass, and perform any dummy pass(es) needed. - * Common subroutine for jpeg_start_decompress and jpeg_start_output. - * Entry: global_state = DSTATE_PRESCAN only if previously suspended. - * Exit: If done, returns TRUE and sets global_state for proper output mode. - * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. - */ - -LOCAL(boolean) -output_pass_setup (j_decompress_ptr cinfo) -{ - if (cinfo->global_state != DSTATE_PRESCAN) { - /* First call: do pass setup */ - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; - cinfo->global_state = DSTATE_PRESCAN; - } - /* Loop over any required dummy passes */ - while (cinfo->master->is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Crank through the dummy pass */ - while (cinfo->output_scanline < cinfo->output_height) { - JDIMENSION last_scanline; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* Process some data */ - last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); - if (cinfo->output_scanline == last_scanline) - return FALSE; /* No progress made, must suspend */ - } - /* Finish up dummy pass, and set up for another one */ - (*cinfo->master->finish_output_pass) (cinfo); - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } - /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. - */ - cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; - return TRUE; -} - - -/* - * Read some scanlines of data from the JPEG decompressor. - * - * The return value will be the number of lines actually read. - * This may be less than the number requested in several cases, - * including bottom of image, data source suspension, and operating - * modes that emit multiple scanlines at a time. - * - * Note: we warn about excess calls to jpeg_read_scanlines() since - * this likely signals an application programmer error. However, - * an oversize buffer (max_lines > scanlines remaining) is not an error. - */ - -GLOBAL(JDIMENSION) -jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) -{ - JDIMENSION row_ctr; - - if (cinfo->global_state != DSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Process some data */ - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); - cinfo->output_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to read raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL(JDIMENSION) -jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != DSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; - if (max_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Decompress directly into user's buffer. */ - if (! (*cinfo->coef->decompress_data) (cinfo, data)) - return 0; /* suspension forced, can do nothing more */ - - /* OK, we processed one iMCU row. */ - cinfo->output_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} - - -/* Additional entry points for buffered-image mode. */ - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Initialize for an output pass in buffered-image mode. - */ - -GLOBAL(boolean) -jpeg_start_output (j_decompress_ptr cinfo, int scan_number) -{ - if (cinfo->global_state != DSTATE_BUFIMAGE && - cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Limit scan number to valid range */ - if (scan_number <= 0) - scan_number = 1; - if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) - scan_number = cinfo->input_scan_number; - cinfo->output_scan_number = scan_number; - /* Perform any dummy output passes, and set up for the real pass */ - return output_pass_setup(cinfo); -} - - -/* - * Finish up after an output pass in buffered-image mode. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_output (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { - /* Terminate this pass. */ - /* We do not require the whole pass to have been completed. */ - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_BUFPOST; - } else if (cinfo->global_state != DSTATE_BUFPOST) { - /* BUFPOST = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read markers looking for SOS or EOI */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ +/* + * jdapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->coef->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/Source/External/LibJPEG/jdatadst.c b/Source/External/LibJPEG/jdatadst.c index 2ece4e9..a8f6fb0 100644 --- a/Source/External/LibJPEG/jdatadst.c +++ b/Source/External/LibJPEG/jdatadst.c @@ -1,151 +1,151 @@ -/* - * jdatadst.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains compression data destination routines for the case of - * emitting JPEG data to a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * destination manager. - * IMPORTANT: we assume that fwrite() will correctly transcribe an array of - * JOCTETs into 8-bit-wide elements on external storage. If char is wider - * than 8 bits on your machine, you may need to do some tweaking. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" - - -/* Expanded data destination object for stdio output */ - -typedef struct { - struct jpeg_destination_mgr pub; /* public fields */ - - FILE * outfile; /* target stream */ - JOCTET * buffer; /* start of buffer */ -} my_destination_mgr; - -typedef my_destination_mgr * my_dest_ptr; - -#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ - - -/* - * Initialize destination --- called by jpeg_start_compress - * before any data is actually written. - */ - -METHODDEF(void) -init_destination (j_compress_ptr cinfo) -{ - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - - /* Allocate the output buffer --- it will be released when done with image */ - dest->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; -} - - -/* - * Empty the output buffer --- called whenever buffer fills up. - * - * In typical applications, this should write the entire output buffer - * (ignoring the current state of next_output_byte & free_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been dumped. - * - * In applications that need to be able to suspend compression due to output - * overrun, a FALSE return indicates that the buffer cannot be emptied now. - * In this situation, the compressor will return to its caller (possibly with - * an indication that it has not accepted all the supplied scanlines). The - * application should resume compression after it has made more room in the - * output buffer. Note that there are substantial restrictions on the use of - * suspension --- see the documentation. - * - * When suspending, the compressor will back up to a convenient restart point - * (typically the start of the current MCU). next_output_byte & free_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point will be regenerated after resumption, so do not - * write it out when emptying the buffer externally. - */ - -METHODDEF(boolean) -empty_output_buffer (j_compress_ptr cinfo) -{ - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - - if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != - (size_t) OUTPUT_BUF_SIZE) - ERREXIT(cinfo, JERR_FILE_WRITE); - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - - return TRUE; -} - - -/* - * Terminate destination --- called by jpeg_finish_compress - * after all data has been written. Usually needs to flush buffer. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - -METHODDEF(void) -term_destination (j_compress_ptr cinfo) -{ - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - - /* Write any data remaining in the buffer */ - if (datacount > 0) { - if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) - ERREXIT(cinfo, JERR_FILE_WRITE); - } - fflush(dest->outfile); - /* Make sure we wrote the output file OK */ - if (ferror(dest->outfile)) - ERREXIT(cinfo, JERR_FILE_WRITE); -} - - -/* - * Prepare for output to a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing compression. - */ - -GLOBAL(void) -jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) -{ - my_dest_ptr dest; - - /* The destination object is made permanent so that multiple JPEG images - * can be written to the same file without re-executing jpeg_stdio_dest. - * This makes it dangerous to use this manager and a different destination - * manager serially with the same JPEG object, because their private object - * sizes may be different. Caveat programmer. - */ - if (cinfo->dest == NULL) { /* first time for this JPEG object? */ - cinfo->dest = (struct jpeg_destination_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_destination_mgr)); - } - - dest = (my_dest_ptr) cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - dest->outfile = outfile; -} +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/Source/External/LibJPEG/jdatasrc.c b/Source/External/LibJPEG/jdatasrc.c index 29b6983..edc752b 100644 --- a/Source/External/LibJPEG/jdatasrc.c +++ b/Source/External/LibJPEG/jdatasrc.c @@ -1,212 +1,212 @@ -/* - * jdatasrc.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains decompression data source routines for the case of - * reading JPEG data from a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * source manager. - * IMPORTANT: we assume that fread() will correctly transcribe an array of - * JOCTETs from 8-bit-wide elements on external storage. If char is wider - * than 8 bits on your machine, you may need to do some tweaking. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" - - -/* Expanded data source object for stdio input */ - -typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - - FILE * infile; /* source stream */ - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ -} my_source_mgr; - -typedef my_source_mgr * my_src_ptr; - -#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ - - -/* - * Initialize source --- called by jpeg_read_header - * before any data is actually read. - */ - -METHODDEF(void) -init_source (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; -} - - -/* - * Fill the input buffer --- called whenever buffer is emptied. - * - * In typical applications, this should read fresh data into the buffer - * (ignoring the current state of next_input_byte & bytes_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been reloaded. It is not necessary to - * fill the buffer entirely, only to obtain at least one more byte. - * - * There is no such thing as an EOF return. If the end of the file has been - * reached, the routine has a choice of ERREXIT() or inserting fake data into - * the buffer. In most cases, generating a warning message and inserting a - * fake EOI marker is the best course of action --- this will allow the - * decompressor to output however much of the image is there. However, - * the resulting error message is misleading if the real problem is an empty - * input file, so we handle that case specially. - * - * In applications that need to be able to suspend compression due to input - * not being available yet, a FALSE return indicates that no more data can be - * obtained right now, but more may be forthcoming later. In this situation, - * the decompressor will return to its caller (with an indication of the - * number of scanlines it has read, if any). The application should resume - * decompression after it has loaded more data into the input buffer. Note - * that there are substantial restrictions on the use of suspension --- see - * the documentation. - * - * When suspending, the decompressor will back up to a convenient restart point - * (typically the start of the current MCU). next_input_byte & bytes_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point must be rescanned after resumption, so move it to - * the front of the buffer rather than discarding it. - */ - -METHODDEF(boolean) -fill_input_buffer (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes; - - nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); - - if (nbytes <= 0) { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; - - return TRUE; -} - - -/* - * Skip data --- used to skip over a potentially large amount of - * uninteresting data (such as an APPn marker). - * - * Writers of suspendable-input applications must note that skip_input_data - * is not granted the right to give a suspension return. If the skip extends - * beyond the data currently in the buffer, the buffer can be marked empty so - * that the next read will cause a fill_input_buffer call that can suspend. - * Arranging for additional bytes to be discarded before reloading the input - * buffer is the application writer's problem. - */ - -METHODDEF(void) -skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - - -/* - * An additional method that can be provided by data source modules is the - * resync_to_restart method for error recovery in the presence of RST markers. - * For the moment, this source module just uses the default resync method - * provided by the JPEG library. That method assumes that no backtracking - * is possible. - */ - - -/* - * Terminate source --- called by jpeg_finish_decompress - * after all data has been read. Often a no-op. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - -METHODDEF(void) -term_source (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * Prepare for input from a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing decompression. - */ - -GLOBAL(void) -jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) -{ - my_src_ptr src; - - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * SIZEOF(JOCTET)); - } - - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ -} +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/Source/External/LibJPEG/jdcoefct.c b/Source/External/LibJPEG/jdcoefct.c index 992bd10..4938d20 100644 --- a/Source/External/LibJPEG/jdcoefct.c +++ b/Source/External/LibJPEG/jdcoefct.c @@ -1,736 +1,736 @@ -/* - * jdcoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. - * The coefficient buffer lies between entropy decoding and inverse-DCT steps. - * - * In buffered-image mode, this controller is the interface between - * input-oriented processing and output-oriented processing. - * Also, the input side (only) is used when reading a file for transcoding. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -/* Block smoothing is only applicable for progressive JPEG, so: */ -#ifndef D_PROGRESSIVE_SUPPORTED -#undef BLOCK_SMOOTHING_SUPPORTED -#endif - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_coef_controller pub; /* public fields */ - - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ - JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, - * and let the entropy decoder write into that workspace each time. - * (On 80x86, the workspace is FAR even though it's not really very big; - * this is to keep the module interfaces unchanged when a large coefficient - * buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays; it is used only by the input side. - */ - JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -#endif - -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* When doing block smoothing, we latch coefficient Al values here */ - int * coef_bits_latch; -#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ -#endif -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - -/* Forward declarations */ -METHODDEF(int) decompress_onepass - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif -#ifdef BLOCK_SMOOTHING_SUPPORTED -LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); -METHODDEF(int) decompress_smooth_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->MCU_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - cinfo->input_iMCU_row = 0; - start_iMCU_row(cinfo); -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF(void) -start_output_pass (j_decompress_ptr cinfo) -{ -#ifdef BLOCK_SMOOTHING_SUPPORTED - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* If multipass, check to see whether to use block smoothing on this pass */ - if (coef->pub.coef_arrays != NULL) { - if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; - else - coef->pub.decompress_data = decompress_data; - } -#endif - cinfo->output_iMCU_row = 0; -} - - -/* - * Decompress and return some data in the single-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(int) -decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; - JDIMENSION start_col, output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Loop to process as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - jzero_far((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - /* Determine where data should go in output_buf and do the IDCT thing. - * We skip dummy blocks at the right and bottom edges (but blkn gets - * incremented past them!). Note the inner loop relies on having - * allocated the MCU_buffer[] blocks sequentially. - */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) { - blkn += compptr->MCU_blocks; - continue; - } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; - useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->DCT_scaled_size; - start_col = MCU_col_num * compptr->MCU_sample_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_scaled_size; - } - } - blkn += compptr->MCU_width; - output_ptr += compptr->DCT_scaled_size; - } - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - cinfo->output_iMCU_row++; - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Dummy consume-input routine for single-pass operation. - */ - -METHODDEF(int) -dummy_consume_data (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; /* Always indicate nothing was done */ -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Consume input data and store it in the full-image coefficient buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor block rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - -METHODDEF(int) -consume_data (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Note: entropy decoder expects buffer to be zeroed, - * but this is handled automatically by the memory manager - * because we requested a pre-zeroed array. - */ - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to fetch the MCU. */ - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Decompress and return some data in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - -METHODDEF(int) -decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num; - int ci, block_row, block_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - output_col = 0; - for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, - output_ptr, output_col); - buffer_ptr++; - output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -#ifdef BLOCK_SMOOTHING_SUPPORTED - -/* - * This code applies interblock smoothing as described by section K.8 - * of the JPEG standard: the first 5 AC coefficients are estimated from - * the DC values of a DCT block and its 8 neighboring blocks. - * We apply smoothing only for progressive JPEG decoding, and only if - * the coefficients it can estimate are not yet known to full precision. - */ - -/* Natural-order array positions of the first 5 zigzag-order coefficients */ -#define Q01_POS 1 -#define Q10_POS 8 -#define Q20_POS 16 -#define Q11_POS 9 -#define Q02_POS 2 - -/* - * Determine whether block smoothing is applicable and safe. - * We also latch the current states of the coef_bits[] entries for the - * AC coefficients; otherwise, if the input side of the decompressor - * advances into a new scan, we might think the coefficients are known - * more accurately than they really are. - */ - -LOCAL(boolean) -smoothing_ok (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - boolean smoothing_useful = FALSE; - int ci, coefi; - jpeg_component_info *compptr; - JQUANT_TBL * qtable; - int * coef_bits; - int * coef_bits_latch; - - if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) - return FALSE; - - /* Allocate latch area if not already done */ - if (coef->coef_bits_latch == NULL) - coef->coef_bits_latch = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * - (SAVED_COEFS * SIZEOF(int))); - coef_bits_latch = coef->coef_bits_latch; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* All components' quantization values must already be latched. */ - if ((qtable = compptr->quant_table) == NULL) - return FALSE; - /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ - if (qtable->quantval[0] == 0 || - qtable->quantval[Q01_POS] == 0 || - qtable->quantval[Q10_POS] == 0 || - qtable->quantval[Q20_POS] == 0 || - qtable->quantval[Q11_POS] == 0 || - qtable->quantval[Q02_POS] == 0) - return FALSE; - /* DC values must be at least partly known for all components. */ - coef_bits = cinfo->coef_bits[ci]; - if (coef_bits[0] < 0) - return FALSE; - /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ - for (coefi = 1; coefi <= 5; coefi++) { - coef_bits_latch[coefi] = coef_bits[coefi]; - if (coef_bits[coefi] != 0) - smoothing_useful = TRUE; - } - coef_bits_latch += SAVED_COEFS; - } - - return smoothing_useful; -} - - -/* - * Variant of decompress_data for use when doing block smoothing. - */ - -METHODDEF(int) -decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num, last_block_column; - int ci, block_row, block_rows, access_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr, prev_block_row, next_block_row; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - boolean first_row, last_row; - JBLOCK workspace; - int *coef_bits; - JQUANT_TBL *quanttbl; - INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; - int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; - int Al, pred; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if (cinfo->input_scan_number == cinfo->output_scan_number) { - /* If input is working on current scan, we ordinarily want it to - * have completed the current row. But if input scan is DC, - * we want it to keep one row ahead so that next block row's DC - * values are up to date. - */ - JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; - if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) - break; - } - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) { - block_rows = compptr->v_samp_factor; - access_rows = block_rows * 2; /* this and next iMCU row */ - last_row = FALSE; - } else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - access_rows = block_rows; /* this iMCU row only */ - last_row = TRUE; - } - /* Align the virtual buffer for this component. */ - if (cinfo->output_iMCU_row > 0) { - access_rows += compptr->v_samp_factor; /* prior iMCU row too */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, - (JDIMENSION) access_rows, FALSE); - buffer += compptr->v_samp_factor; /* point to current iMCU row */ - first_row = FALSE; - } else { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); - first_row = TRUE; - } - /* Fetch component-dependent info */ - coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); - quanttbl = compptr->quant_table; - Q00 = quanttbl->quantval[0]; - Q01 = quanttbl->quantval[Q01_POS]; - Q10 = quanttbl->quantval[Q10_POS]; - Q20 = quanttbl->quantval[Q20_POS]; - Q11 = quanttbl->quantval[Q11_POS]; - Q02 = quanttbl->quantval[Q02_POS]; - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - if (first_row && block_row == 0) - prev_block_row = buffer_ptr; - else - prev_block_row = buffer[block_row-1]; - if (last_row && block_row == block_rows-1) - next_block_row = buffer_ptr; - else - next_block_row = buffer[block_row+1]; - /* We fetch the surrounding DC values using a sliding-register approach. - * Initialize all nine here so as to do the right thing on narrow pics. - */ - DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; - DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; - DC7 = DC8 = DC9 = (int) next_block_row[0][0]; - output_col = 0; - last_block_column = compptr->width_in_blocks - 1; - for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ - jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ - if (block_num < last_block_column) { - DC3 = (int) prev_block_row[1][0]; - DC6 = (int) buffer_ptr[1][0]; - DC9 = (int) next_block_row[1][0]; - } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ - if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { - num = 36 * Q00 * (DC4 - DC6); - if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* BLOCK_SMOOTHING_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL(void) -jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_d_coef_controller *) coef; - coef->pub.start_input_pass = start_input_pass; - coef->pub.start_output_pass = start_output_pass; -#ifdef BLOCK_SMOOTHING_SUPPORTED - coef->coef_bits_latch = NULL; -#endif - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - /* Note we ask for a pre-zeroed array. */ - int ci, access_rows; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - access_rows = compptr->v_samp_factor; -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) - access_rows *= 3; -#endif - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); - } - coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; - coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; - coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ - } -} +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (coef->pub.coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_scaled_size; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->progressive_mode) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/Source/External/LibJPEG/jdcolor.c b/Source/External/LibJPEG/jdcolor.c index fd7b138..6c04dfe 100644 --- a/Source/External/LibJPEG/jdcolor.c +++ b/Source/External/LibJPEG/jdcolor.c @@ -1,396 +1,396 @@ -/* - * jdcolor.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains output colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_deconverter pub; /* public fields */ - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ -} my_color_deconverter; - -typedef my_color_deconverter * my_cconvert_ptr; - - -/**************** YCbCr -> RGB conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * Notice that Y, being an integral input, does not contribute any fraction - * so it need not participate in the rounding. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The Cr=>R and Cb=>B values can be rounded to integers in advance; the - * values for the G calculation are left scaled up, since we must add them - * together before rounding. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - int i; - INT32 x; - SHIFT_TEMPS - - cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; - } -} - - -/* - * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF(void) -ycc_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/**************** Cases other than YCbCr -> RGB **************/ - - -/* - * Color conversion for no colorspace change: just copy the data, - * converting from separate-planes to interleaved representation. - */ - -METHODDEF(void) -null_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW inptr, outptr; - register JDIMENSION count; - register int num_components = cinfo->num_components; - JDIMENSION num_cols = cinfo->output_width; - int ci; - - while (--num_rows >= 0) { - for (ci = 0; ci < num_components; ci++) { - inptr = input_buf[ci][input_row]; - outptr = output_buf[0] + ci; - for (count = num_cols; count > 0; count--) { - *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += num_components; - } - } - input_row++; - output_buf++; - } -} - - -/* - * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which - * we just copy the Y (luminance) component and ignore chrominance. - */ - -METHODDEF(void) -grayscale_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); -} - - -/* - * Convert grayscale to RGB: just duplicate the graylevel three times. - * This is provided to support applications that don't want to cope - * with grayscale as a separate case. - */ - -METHODDEF(void) -gray_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW inptr, outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr = input_buf[0][input_row++]; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * Adobe-style YCCK->CMYK conversion. - * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same - * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. - */ - -METHODDEF(void) -ycck_cmyk_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - inptr3 = input_buf[3][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ - /* K passes through unchanged */ - outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ - outptr += 4; - } - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF(void) -start_pass_dcolor (j_decompress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for output colorspace conversion. - */ - -GLOBAL(void) -jinit_color_deconverter (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - int ci; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_deconverter)); - cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; - cconvert->pub.start_pass = start_pass_dcolor; - - /* Make sure num_components agrees with jpeg_color_space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_RGB: - case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->num_components < 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - } - - /* Set out_color_components and conversion method based on requested space. - * Also clear the component_needed flags for any unused components, - * so that earlier pipeline stages can avoid useless computation. - */ - - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || - cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert; - /* For color->grayscale conversion, only the Y (0) component is needed */ - for (ci = 1; ci < cinfo->num_components; ci++) - cinfo->comp_info[ci].component_needed = FALSE; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; - } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - default: - /* Permit null conversion to same output space */ - if (cinfo->out_color_space == cinfo->jpeg_color_space) { - cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; - } else /* unsupported non-null conversion */ - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - } - - if (cinfo->quantize_colors) - cinfo->output_components = 1; /* single colormapped output component */ - else - cinfo->output_components = cinfo->out_color_components; -} +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/Source/External/LibJPEG/jdct.h b/Source/External/LibJPEG/jdct.h index b664cab..04192a2 100644 --- a/Source/External/LibJPEG/jdct.h +++ b/Source/External/LibJPEG/jdct.h @@ -1,176 +1,176 @@ -/* - * jdct.h - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the forward and - * inverse DCT modules. These declarations are private to the DCT managers - * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease - * machine-dependent tuning (e.g., assembly coding). - */ - - -/* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef int DCTELEM; /* 16 or 32 bits is fine */ -#else -typedef INT32 DCTELEM; /* must have 32 bits */ -#endif - -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); - - -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - -typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ -#if BITS_IN_JSAMPLE == 8 -typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ -#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ -#else -typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ -#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ -#endif -typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ - - -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_fdct_islow jFDislow -#define jpeg_fdct_ifast jFDifast -#define jpeg_fdct_float jFDfloat -#define jpeg_idct_islow jRDislow -#define jpeg_idct_ifast jRDifast -#define jpeg_idct_float jRDfloat -#define jpeg_idct_4x4 jRD4x4 -#define jpeg_idct_2x2 jRD2x2 -#define jpeg_idct_1x1 jRD1x1 -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Extern declarations for the forward and inverse DCT routines. */ - -EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); - -EXTERN(void) jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); - - -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - -#define ONE ((INT32) 1) -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif - -#ifndef MULTIPLY16C16 /* default definition */ -#define MULTIPLY16C16(var,const) ((var) * (const)) -#endif - -/* Same except both inputs are variables. */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) -#endif - -#ifndef MULTIPLY16V16 /* default definition */ -#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) -#endif +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/Source/External/LibJPEG/jddctmgr.c b/Source/External/LibJPEG/jddctmgr.c index 0e44eb1..bbf8d0e 100644 --- a/Source/External/LibJPEG/jddctmgr.c +++ b/Source/External/LibJPEG/jddctmgr.c @@ -1,269 +1,269 @@ -/* - * jddctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the inverse-DCT management logic. - * This code selects a particular IDCT implementation to be used, - * and it performs related housekeeping chores. No code in this file - * is executed per IDCT step, only during output pass setup. - * - * Note that the IDCT routines are responsible for performing coefficient - * dequantization as well as the IDCT proper. This module sets up the - * dequantization multiplier table needed by the IDCT routine. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* - * The decompressor input side (jdinput.c) saves away the appropriate - * quantization table for each component at the start of the first scan - * involving that component. (This is necessary in order to correctly - * decode files that reuse Q-table slots.) - * When we are ready to make an output pass, the saved Q-table is converted - * to a multiplier table that will actually be used by the IDCT routine. - * The multiplier table contents are IDCT-method-dependent. To support - * application changes in IDCT method between scans, we can remake the - * multiplier tables if necessary. - * In buffered-image mode, the first output pass may occur before any data - * has been seen for some components, and thus before their Q-tables have - * been saved away. To handle this case, multiplier tables are preset - * to zeroes; the result of the IDCT will be a neutral gray level. - */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_inverse_dct pub; /* public fields */ - - /* This array contains the IDCT method code that each multiplier table - * is currently set up for, or -1 if it's not yet set up. - * The actual multiplier tables are pointed to by dct_table in the - * per-component comp_info structures. - */ - int cur_method[MAX_COMPONENTS]; -} my_idct_controller; - -typedef my_idct_controller * my_idct_ptr; - - -/* Allocated multiplier tables: big enough for any supported variant */ - -typedef union { - ISLOW_MULT_TYPE islow_array[DCTSIZE2]; -#ifdef DCT_IFAST_SUPPORTED - IFAST_MULT_TYPE ifast_array[DCTSIZE2]; -#endif -#ifdef DCT_FLOAT_SUPPORTED - FLOAT_MULT_TYPE float_array[DCTSIZE2]; -#endif -} multiplier_table; - - -/* The current scaled-IDCT routines require ISLOW-style multiplier tables, - * so be sure to compile that code if either ISLOW or SCALING is requested. - */ -#ifdef DCT_ISLOW_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#else -#ifdef IDCT_SCALING_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#endif -#endif - - -/* - * Prepare for an output pass. - * Here we select the proper IDCT routine for each component and build - * a matching multiplier table. - */ - -METHODDEF(void) -start_pass (j_decompress_ptr cinfo) -{ - my_idct_ptr idct = (my_idct_ptr) cinfo->idct; - int ci, i; - jpeg_component_info *compptr; - int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; - JQUANT_TBL * qtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->DCT_scaled_size) { -#ifdef IDCT_SCALING_SUPPORTED - case 1: - method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 2: - method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 4: - method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; -#endif - case DCTSIZE: - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - method_ptr = jpeg_idct_islow; - method = JDCT_ISLOW; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - method_ptr = jpeg_idct_ifast; - method = JDCT_IFAST; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - method_ptr = jpeg_idct_float; - method = JDCT_FLOAT; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - break; - default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); - break; - } - idct->pub.inverse_DCT[ci] = method_ptr; - /* Create multiplier table from quant table. - * However, we can skip this if the component is uninteresting - * or if we already built the table. Also, if no quant table - * has yet been saved for the component, we leave the - * multiplier table all-zero; we'll be reading zeroes from the - * coefficient controller's buffer anyway. - */ - if (! compptr->component_needed || idct->cur_method[ci] == method) - continue; - qtbl = compptr->quant_table; - if (qtbl == NULL) /* happens if no data yet for component */ - continue; - idct->cur_method[ci] = method; - switch (method) { -#ifdef PROVIDE_ISLOW_TABLES - case JDCT_ISLOW: - { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored as ints to ensure access efficiency. - */ - ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; - for (i = 0; i < DCTSIZE2; i++) { - ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; - } - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. - */ - IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - for (i = 0; i < DCTSIZE2; i++) { - ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - */ - FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col]); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Initialize IDCT manager. - */ - -GLOBAL(void) -jinit_inverse_dct (j_decompress_ptr cinfo) -{ - my_idct_ptr idct; - int ci; - jpeg_component_info *compptr; - - idct = (my_idct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_idct_controller)); - cinfo->idct = (struct jpeg_inverse_dct *) idct; - idct->pub.start_pass = start_pass; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate and pre-zero a multiplier table for each component */ - compptr->dct_table = - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(multiplier_table)); - MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); - /* Mark multiplier table not yet set up for any method */ - idct->cur_method[ci] = -1; - } -} +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} my_idct_controller; + +typedef my_idct_controller * my_idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->DCT_scaled_size) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + my_idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (my_idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_idct_controller)); + cinfo->idct = (struct jpeg_inverse_dct *) idct; + idct->pub.start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/Source/External/LibJPEG/jdhuff.c b/Source/External/LibJPEG/jdhuff.c index b2ad66d..b5ba39f 100644 --- a/Source/External/LibJPEG/jdhuff.c +++ b/Source/External/LibJPEG/jdhuff.c @@ -1,651 +1,651 @@ -/* - * jdhuff.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ - - -/* - * Expanded entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - - /* Precalculated info set up by start_pass for use in decode_mcu: */ - - /* Pointers to derived tables to be used for each block within an MCU */ - d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - /* Whether we care about the DC and AC coefficient values for each block */ - boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; - boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; -} huff_entropy_decoder; - -typedef huff_entropy_decoder * huff_entropy_ptr; - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, blkn, dctbl, actbl; - jpeg_component_info * compptr; - - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Precalculate decoding info for each block in an MCU of this scan */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - entropy->dc_needed[blkn] = TRUE; - /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); - } else { - entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; - } - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jdphuff.c. - */ - -GLOBAL(void) -jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, - d_derived_tbl ** pdtbl) -{ - JHUFF_TBL *htbl; - d_derived_tbl *dtbl; - int p, i, l, si, numsymbols; - int lookbits, ctr; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ - if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (d_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_derived_tbl)); - dtbl = *pdtbl; - dtbl->pub = htbl; /* fill in back link */ - - /* Figure C.1: make table of Huffman code length for each symbol */ - - p = 0; - for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - numsymbols = p; - - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - - code = 0; - si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - si++; - } - - /* Figure F.15: generate decoding tables for bit-sequential decoding */ - - p = 0; - for (l = 1; l <= 16; l++) { - if (htbl->bits[l]) { - /* valoffset[l] = huffval[] index of 1st symbol of code length l, - * minus the minimum code of length l - */ - dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; - p += htbl->bits[l]; - dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ - } else { - dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ - } - } - dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ - - /* Compute lookahead tables to speed up decoding. - * First we set all the table entries to 0, indicating "too long"; - * then we iterate through the Huffman codes that are short enough and - * fill in all the entries that correspond to bit sequences starting - * with that code. - */ - - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); - - p = 0; - for (l = 1; l <= HUFF_LOOKAHEAD; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { - /* l = current code's length, p = its index in huffcode[] & huffval[]. */ - /* Generate left-justified code followed by all possible bit sequences */ - lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); - for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; - lookbits++; - } - } - } - - /* Validate symbols as being reasonable. - * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) - */ - if (isDC) { - for (i = 0; i < numsymbols; i++) { - int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - } - } -} - - -/* - * Out-of-line code for bit fetching (shared with jdphuff.c). - * See jdhuff.h for info about usage. - * Note: current values of get_buffer and bits_left are passed as parameters, - * but are returned in the corresponding fields of the state struct. - * - * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width - * of get_buffer to be used. (On machines with wider words, an even larger - * buffer could be used.) However, on some machines 32-bit shifts are - * quite slow and take time proportional to the number of places shifted. - * (This is true with most PC compilers, for instance.) In this case it may - * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the - * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. - */ - -#ifdef SLOW_SHIFT_32 -#define MIN_GET_BITS 15 /* minimum allowable value */ -#else -#define MIN_GET_BITS (BIT_BUF_SIZE-7) -#endif - - -GLOBAL(boolean) -jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) -/* Load up the bit buffer to a depth of at least nbits */ -{ - /* Copy heavily used state fields into locals (hopefully registers) */ - register const JOCTET * next_input_byte = state->next_input_byte; - register size_t bytes_in_buffer = state->bytes_in_buffer; - j_decompress_ptr cinfo = state->cinfo; - - /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ - /* (It is assumed that no request will be for more than that many bits.) */ - /* We fail to do so only if we hit a marker or are forced to suspend. */ - - if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ - while (bits_left < MIN_GET_BITS) { - register int c; - - /* Attempt to read a byte */ - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - - /* If it's 0xFF, check and discard stuffed zero byte */ - if (c == 0xFF) { - /* Loop here to discard any padding FF's on terminating marker, - * so that we can save a valid unread_marker value. NOTE: we will - * accept multiple FF's followed by a 0 as meaning a single FF data - * byte. This data pattern is not valid according to the standard. - */ - do { - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - } while (c == 0xFF); - - if (c == 0) { - /* Found FF/00, which represents an FF data byte */ - c = 0xFF; - } else { - /* Oops, it's actually a marker indicating end of compressed data. - * Save the marker code for later use. - * Fine point: it might appear that we should save the marker into - * bitread working state, not straight into permanent state. But - * once we have hit a marker, we cannot need to suspend within the - * current MCU, because we will read no more bytes from the data - * source. So it is OK to update permanent state right away. - */ - cinfo->unread_marker = c; - /* See if we need to insert some fake zero bits. */ - goto no_more_bytes; - } - } - - /* OK, load c into get_buffer */ - get_buffer = (get_buffer << 8) | c; - bits_left += 8; - } /* end while */ - } else { - no_more_bytes: - /* We get here if we've read the marker that terminates the compressed - * data segment. There should be enough bits in the buffer register - * to satisfy the request; if so, no problem. - */ - if (nbits > bits_left) { - /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so that we can produce some kind of image. - * We use a nonvolatile flag to ensure that only one warning message - * appears per data segment. - */ - if (! cinfo->entropy->insufficient_data) { - WARNMS(cinfo, JWRN_HIT_MARKER); - cinfo->entropy->insufficient_data = TRUE; - } - /* Fill the buffer with zero bits */ - get_buffer <<= MIN_GET_BITS - bits_left; - bits_left = MIN_GET_BITS; - } - } - - /* Unload the local registers */ - state->next_input_byte = next_input_byte; - state->bytes_in_buffer = bytes_in_buffer; - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - return TRUE; -} - - -/* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. - */ - -GLOBAL(int) -jpeg_huff_decode (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits) -{ - register int l = min_bits; - register INT32 code; - - /* HUFF_DECODE has determined that the code is at least min_bits */ - /* bits long, so fetch that many bits in one swoop. */ - - CHECK_BIT_BUFFER(*state, l, return -1); - code = GET_BITS(l); - - /* Collect the rest of the Huffman code one bit at a time. */ - /* This is per Figure F.16 in the JPEG spec. */ - - while (code > htbl->maxcode[l]) { - code <<= 1; - CHECK_BIT_BUFFER(*state, 1, return -1); - code |= GET_BITS(1); - l++; - } - - /* Unload the local registers */ - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - /* With garbage input we may reach the sentinel value l = 17. */ - - if (l > 16) { - WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); - return 0; /* fake a zero as the safest result */ - } - - return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Decode and return one MCU's worth of Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * Returns FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) - */ - -METHODDEF(boolean) -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn; - BITREAD_STATE_VARS; - savable_state state; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; - register int s, k, r; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - if (entropy->dc_needed[blkn]) { - /* Convert DC difference to actual value, update last_dc_val */ - int ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ - (*block)[0] = (JCOEF) s; - } - - if (entropy->ac_needed[blkn]) { - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - break; - k += 15; - } - } - - } else { - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - } - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_huff_decoder; - entropy->pub.decode_mcu = decode_mcu; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; - } -} +/* + * jdhuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdphuff.c */ + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; + boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jdphuff.c. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..15. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching (shared with jdphuff.c). + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + if (! cinfo->entropy->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + cinfo->entropy->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/Source/External/LibJPEG/jdhuff.h b/Source/External/LibJPEG/jdhuff.h index 12c0747..ae19b6c 100644 --- a/Source/External/LibJPEG/jdhuff.h +++ b/Source/External/LibJPEG/jdhuff.h @@ -1,201 +1,201 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN(boolean) jpeg_fill_bit_buffer - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN(int) jpeg_huff_decode - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); +/* + * jdhuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c) and the + * progressive decoder (jdphuff.c). No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jMkDDerived +#define jpeg_fill_bit_buffer jFilBitBuf +#define jpeg_huff_decode jHufDecode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/Source/External/LibJPEG/jdinput.c b/Source/External/LibJPEG/jdinput.c index 2d5c747..0c2ac8f 100644 --- a/Source/External/LibJPEG/jdinput.c +++ b/Source/External/LibJPEG/jdinput.c @@ -1,381 +1,381 @@ -/* - * jdinput.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input control logic for the JPEG decompressor. - * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_input_controller pub; /* public fields */ - - boolean inheaders; /* TRUE until first SOS is reached */ -} my_input_controller; - -typedef my_input_controller * my_inputctl_ptr; - - -/* Forward declarations */ -METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); - - -/* - * Routines to calculate various quantities related to the size of the image. - */ - -LOCAL(void) -initial_setup (j_decompress_ptr cinfo) -/* Called once, when first SOS marker is reached */ -{ - int ci; - jpeg_component_info *compptr; - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. - */ - cinfo->min_DCT_scaled_size = DCTSIZE; - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* downsampled_width and downsampled_height will also be overridden by - * jdmaster.c if we are doing full decompression. The transcoder library - * doesn't use these values, but the calling application might. - */ - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed, until color conversion says otherwise */ - compptr->component_needed = TRUE; - /* Mark no quantization table yet saved for component */ - compptr->quant_table = NULL; - } - - /* Compute number of fully interleaved MCU rows. */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - /* Decide whether file contains multiple scans */ - if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) - cinfo->inputctl->has_multiple_scans = TRUE; - else - cinfo->inputctl->has_multiple_scans = FALSE; -} - - -LOCAL(void) -per_scan_setup (j_decompress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_scaled_size; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } -} - - -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - -LOCAL(void) -latch_quant_tables (j_decompress_ptr cinfo) -{ - int ci, qtblno; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; - } -} - - -/* - * Initialize the input modules to read a scan of compressed data. - * The first call to this is done by jdmaster.c after initializing - * the entire decompressor (during jpeg_start_decompress). - * Subsequent calls come from consume_markers, below. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - per_scan_setup(cinfo); - latch_quant_tables(cinfo); - (*cinfo->entropy->start_pass) (cinfo); - (*cinfo->coef->start_input_pass) (cinfo); - cinfo->inputctl->consume_input = cinfo->coef->consume_data; -} - - -/* - * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. - */ - -METHODDEF(void) -finish_input_pass (j_decompress_ptr cinfo) -{ - cinfo->inputctl->consume_input = consume_markers; -} - - -/* - * Read JPEG markers before, between, or after compressed-data scans. - * Change state as necessary when a new scan is reached. - * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. - */ - -METHODDEF(int) -consume_markers (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - int val; - - if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ - return JPEG_REACHED_EOI; - - val = (*cinfo->marker->read_markers) (cinfo); - - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass(cinfo); - } - break; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - break; - case JPEG_SUSPENDED: - break; - } - - return val; -} - - -/* - * Reset state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - - inputctl->pub.consume_input = consume_markers; - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; - /* Reset other modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->marker->reset_marker_reader) (cinfo); - /* Reset progression state -- would be cleaner if entropy decoder did this */ - cinfo->coef_bits = NULL; -} - - -/* - * Initialize the input controller module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl; - - /* Create subobject in permanent pool */ - inputctl = (my_inputctl_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_input_controller)); - cinfo->inputctl = (struct jpeg_input_controller *) inputctl; - /* Initialize method pointers */ - inputctl->pub.consume_input = consume_markers; - inputctl->pub.reset_input_controller = reset_input_controller; - inputctl->pub.start_input_pass = start_input_pass; - inputctl->pub.finish_input_pass = finish_input_pass; - /* Initialize state: can't use reset_input_controller since we don't - * want to try to reset other modules yet. - */ - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; -} +/* + * jdinput.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_DCT_scaled_size = DCTSIZE; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/Source/External/LibJPEG/jdmainct.c b/Source/External/LibJPEG/jdmainct.c index f69853e..c08d635 100644 --- a/Source/External/LibJPEG/jdmainct.c +++ b/Source/External/LibJPEG/jdmainct.c @@ -1,512 +1,512 @@ -/* - * jdmainct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for decompression. - * The main buffer lies between the JPEG decompressor proper and the - * post-processor; it holds downsampled data in the JPEG colorspace. - * - * Note that this code is bypassed in raw-data mode, since the application - * supplies the equivalent of the main buffer in that case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. - * - * Postprocessor input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. (We require DCT_scaled_size values to be - * chosen such that these numbers are integers. In practice DCT_scaled_size - * values will likely be powers of two, so we actually have the stronger - * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) - * Upsampling will typically produce max_v_samp_factor pixel rows from each - * row group (times any additional scale factor that the upsampler is - * applying). - * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. - * - * Depending on the vertical scaling algorithm used, the upsampler may need - * access to the sample row(s) above and below its current input row group. - * The upsampler is required to set need_context_rows TRUE at global selection - * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. - * - * When need_context_rows is TRUE, this controller guarantees that the buffer - * passed to postprocessing contains at least one row group's worth of samples - * above and below the row group(s) being processed. Note that the context - * rows "above" the first passed row group appear at negative row offsets in - * the passed buffer. At the top and bottom of the image, the required - * context rows are manufactured by duplicating the first or last real sample - * row; this avoids having special cases in the upsampling inner loops. - * - * The amount of context is fixed at one row group just because that's a - * convenient number for this controller to work with. The existing - * upsamplers really only need one sample row of context. An upsampler - * supporting arbitrary output rescaling might wish for more than one row - * group of context when shrinking the image; tough, we don't handle that. - * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the DCT_scaled_size values, so that the actual scale factor at - * the upsample step needn't be much less than one.) - * - * To provide the desired context, we have to retain the last two row groups - * of one iMCU row while reading in the next iMCU row. (The last row group - * can't be processed until we have another row group for its below-context, - * and so we have to save the next-to-last group too for its above-context.) - * We could do this most simply by copying data around in our buffer, but - * that'd be very slow. We can avoid copying any data by creating a rather - * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number - * of row groups per iMCU row). We create two sets of redundant pointers to - * the workspace. Labeling the physical row groups 0 to M+1, the synthesized - * pointer lists look like this: - * M+1 M-1 - * master pointer --> 0 master pointer --> 0 - * 1 1 - * ... ... - * M-3 M-3 - * M-2 M - * M-1 M+1 - * M M-2 - * M+1 M-1 - * 0 0 - * We read alternate iMCU rows using each master pointer; thus the last two - * row groups of the previous iMCU row remain un-overwritten in the workspace. - * The pointer lists are set up so that the required context rows appear to - * be adjacent to the proper places when we pass the pointer lists to the - * upsampler. - * - * The above pictures describe the normal state of the pointer lists. - * At top and bottom of the image, we diddle the pointer lists to duplicate - * the first or last sample row as necessary (this is cheaper than copying - * sample rows around). - * - * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that - * situation each iMCU row provides only one row group so the buffering logic - * must be different (eg, we must read two iMCU rows before we can emit the - * first row group). For now, we simply do not support providing context - * rows when min_DCT_scaled_size is 1. That combination seems unlikely to - * be worth providing --- if someone wants a 1/8th-size preview, they probably - * want it quick and dirty, so a context-free upsampler is sufficient. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_main_controller pub; /* public fields */ - - /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - - boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ - JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ - - /* Remaining fields are only used in the context case. */ - - /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ - - int whichptr; /* indicates which pointer set is now in use */ - int context_state; /* process_data state machine status */ - JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ - JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - -/* context_state values: */ -#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ -#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ -#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ - - -/* Forward declarations */ -METHODDEF(void) process_data_simple_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -METHODDEF(void) process_data_context_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) process_data_crank_post - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#endif - - -LOCAL(void) -alloc_funny_pointers (j_decompress_ptr cinfo) -/* Allocate space for the funny pointer lists. - * This is done only once, not once per pass. - */ -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - int ci, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - /* Get top-level space for component array pointers. - * We alloc both arrays with one call to save a few cycles. - */ - mainptr->xbuffer[0] = (JSAMPIMAGE) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - mainptr->xbuffer[1] = mainptr->xbuffer[0] + cinfo->num_components; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - /* Get space for pointer lists --- M+4 row groups in each list. - * We alloc both pointer lists with one call to save a few cycles. - */ - xbuf = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); - xbuf += rgroup; /* want one row group at negative offsets */ - mainptr->xbuffer[0][ci] = xbuf; - xbuf += rgroup * (M + 4); - mainptr->xbuffer[1][ci] = xbuf; - } -} - - -LOCAL(void) -make_funny_pointers (j_decompress_ptr cinfo) -/* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in main->buffer), - * and the space for the pointer lists is allocated too. - * This routine just fills in the curiously ordered lists. - * This will be repeated at the beginning of each pass. - */ -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = mainptr->xbuffer[0][ci]; - xbuf1 = mainptr->xbuffer[1][ci]; - /* First copy the workspace pointers as-is */ - buf = mainptr->buffer[ci]; - for (i = 0; i < rgroup * (M + 2); i++) { - xbuf0[i] = xbuf1[i] = buf[i]; - } - /* In the second list, put the last four row groups in swapped order */ - for (i = 0; i < rgroup * 2; i++) { - xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; - xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; - } - /* The wraparound pointers at top and bottom will be filled later - * (see set_wraparound_pointers, below). Initially we want the "above" - * pointers to duplicate the first actual data line. This only needs - * to happen in xbuffer[0]. - */ - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[0]; - } - } -} - - -LOCAL(void) -set_wraparound_pointers (j_decompress_ptr cinfo) -/* Set up the "wraparound" pointers at top and bottom of the pointer lists. - * This changes the pointer list state from top-of-image to the normal state. - */ -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = mainptr->xbuffer[0][ci]; - xbuf1 = mainptr->xbuffer[1][ci]; - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; - xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; - xbuf0[rgroup*(M+2) + i] = xbuf0[i]; - xbuf1[rgroup*(M+2) + i] = xbuf1[i]; - } - } -} - - -LOCAL(void) -set_bottom_pointers (j_decompress_ptr cinfo) -/* Change the pointer lists to duplicate the last sample row at the bottom - * of the image. whichptr indicates which xbuffer holds the final iMCU row. - * Also sets rowgroups_avail to indicate number of nondummy row groups in row. - */ -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - int ci, i, rgroup, iMCUheight, rows_left; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_scaled_size; - /* Count nondummy sample rows remaining for this component */ - rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); - if (rows_left == 0) rows_left = iMCUheight; - /* Count nondummy row groups. Should get same answer for each component, - * so we need only do it once. - */ - if (ci == 0) { - mainptr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); - } - /* Duplicate the last real sample row rgroup*2 times; this pads out the - * last partial rowgroup and ensures at least one full rowgroup of context. - */ - xbuf = mainptr->xbuffer[mainptr->whichptr][ci]; - for (i = 0; i < rgroup * 2; i++) { - xbuf[rows_left + i] = xbuf[rows_left-1]; - } - } -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->upsample->need_context_rows) { - mainptr->pub.process_data = process_data_context_main; - make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - mainptr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - mainptr->context_state = CTX_PREPARE_FOR_IMCU; - mainptr->iMCU_row_ctr = 0; - } else { - /* Simple case with no context needed */ - mainptr->pub.process_data = process_data_simple_main; - } - mainptr->buffer_full = FALSE; /* Mark buffer empty */ - mainptr->rowgroup_ctr = 0; - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_CRANK_DEST: - /* For last pass of 2-pass quantization, just crank the postprocessor */ - mainptr->pub.process_data = process_data_crank_post; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This handles the simple case where no context is required. - */ - -METHODDEF(void) -process_data_simple_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - JDIMENSION rowgroups_avail; - - /* Read input data if we haven't filled the main buffer yet */ - if (! mainptr->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, mainptr->buffer)) - return; /* suspension forced, can do nothing more */ - mainptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - } - - /* There are always min_DCT_scaled_size row groups in an iMCU row. */ - rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; - /* Note: at the bottom of the image, we may pass extra garbage row groups - * to the postprocessor. The postprocessor has to check for bottom - * of image anyway (at row resolution), so no point in us doing it too. - */ - - /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, mainptr->buffer, - &mainptr->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - - /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ - if (mainptr->rowgroup_ctr >= rowgroups_avail) { - mainptr->buffer_full = FALSE; - mainptr->rowgroup_ctr = 0; - } -} - - -/* - * Process some data. - * This handles the case where context rows must be provided. - */ - -METHODDEF(void) -process_data_context_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr mainptr = (my_main_ptr) cinfo->main; - - /* Read input data if we haven't filled the main buffer yet */ - if (! mainptr->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, - mainptr->xbuffer[mainptr->whichptr])) - return; /* suspension forced, can do nothing more */ - mainptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - mainptr->iMCU_row_ctr++; /* count rows received */ - } - - /* Postprocessor typically will not swallow all the input data it is handed - * in one call (due to filling the output buffer first). Must be prepared - * to exit and restart. This switch lets us keep track of how far we got. - * Note that each case falls through to the next on successful completion. - */ - switch (mainptr->context_state) { - case CTX_POSTPONED_ROW: - /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, mainptr->xbuffer[mainptr->whichptr], - &mainptr->rowgroup_ctr, mainptr->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (mainptr->rowgroup_ctr < mainptr->rowgroups_avail) - return; /* Need to suspend */ - mainptr->context_state = CTX_PREPARE_FOR_IMCU; - if (*out_row_ctr >= out_rows_avail) - return; /* Postprocessor exactly filled output buf */ - /*FALLTHROUGH*/ - case CTX_PREPARE_FOR_IMCU: - /* Prepare to process first M-1 row groups of this iMCU row */ - mainptr->rowgroup_ctr = 0; - mainptr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); - /* Check for bottom of image: if so, tweak pointers to "duplicate" - * the last sample row, and adjust rowgroups_avail to ignore padding rows. - */ - if (mainptr->iMCU_row_ctr == cinfo->total_iMCU_rows) - set_bottom_pointers(cinfo); - mainptr->context_state = CTX_PROCESS_IMCU; - /*FALLTHROUGH*/ - case CTX_PROCESS_IMCU: - /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, mainptr->xbuffer[mainptr->whichptr], - &mainptr->rowgroup_ctr, mainptr->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (mainptr->rowgroup_ctr < mainptr->rowgroups_avail) - return; /* Need to suspend */ - /* After the first iMCU, change wraparound pointers to normal state */ - if (mainptr->iMCU_row_ctr == 1) - set_wraparound_pointers(cinfo); - /* Prepare to load new iMCU row using other xbuffer list */ - mainptr->whichptr ^= 1; /* 0=>1 or 1=>0 */ - mainptr->buffer_full = FALSE; - /* Still need to process last row group of this iMCU row, */ - /* which is saved at index M+1 of the other xbuffer */ - mainptr->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); - mainptr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); - mainptr->context_state = CTX_POSTPONED_ROW; - } -} - - -/* - * Process some data. - * Final pass of two-pass quantization: just call the postprocessor. - * Source data will be the postprocessor controller's internal buffer. - */ - -#ifdef QUANT_2PASS_SUPPORTED - -METHODDEF(void) -process_data_crank_post (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL(void) -jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr mainptr; - int ci, rgroup, ngroups; - jpeg_component_info *compptr; - - mainptr = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_d_main_controller *) mainptr; - mainptr->pub.start_pass = start_pass_main; - - if (need_full_buffer) /* shouldn't happen */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Allocate the workspace. - * ngroups is the number of row groups we need. - */ - if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ - ERREXIT(cinfo, JERR_NOTIMPL); - alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_scaled_size + 2; - } else { - ngroups = cinfo->min_DCT_scaled_size; - } - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - mainptr->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * compptr->DCT_scaled_size, - (JDIMENSION) (rgroup * ngroups)); - } -} +/* + * jdmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size + * values will likely be powers of two, so we actually have the stronger + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the DCT_scaled_size values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + mainptr->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + mainptr->xbuffer[1] = mainptr->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + mainptr->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + mainptr->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = mainptr->xbuffer[0][ci]; + xbuf1 = mainptr->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = mainptr->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = mainptr->xbuffer[0][ci]; + xbuf1 = mainptr->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + mainptr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = mainptr->xbuffer[mainptr->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + mainptr->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + mainptr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mainptr->context_state = CTX_PREPARE_FOR_IMCU; + mainptr->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + mainptr->pub.process_data = process_data_simple_main; + } + mainptr->buffer_full = FALSE; /* Mark buffer empty */ + mainptr->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + mainptr->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mainptr->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, mainptr->buffer)) + return; /* suspension forced, can do nothing more */ + mainptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, mainptr->buffer, + &mainptr->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (mainptr->rowgroup_ctr >= rowgroups_avail) { + mainptr->buffer_full = FALSE; + mainptr->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mainptr = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mainptr->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + mainptr->xbuffer[mainptr->whichptr])) + return; /* suspension forced, can do nothing more */ + mainptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mainptr->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (mainptr->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, mainptr->xbuffer[mainptr->whichptr], + &mainptr->rowgroup_ctr, mainptr->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mainptr->rowgroup_ctr < mainptr->rowgroups_avail) + return; /* Need to suspend */ + mainptr->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + mainptr->rowgroup_ctr = 0; + mainptr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (mainptr->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + mainptr->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, mainptr->xbuffer[mainptr->whichptr], + &mainptr->rowgroup_ctr, mainptr->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mainptr->rowgroup_ctr < mainptr->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (mainptr->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + mainptr->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mainptr->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + mainptr->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + mainptr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + mainptr->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mainptr; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + mainptr = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) mainptr; + mainptr->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_scaled_size + 2; + } else { + ngroups = cinfo->min_DCT_scaled_size; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + mainptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_scaled_size, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/Source/External/LibJPEG/jdmarker.c b/Source/External/LibJPEG/jdmarker.c index 9811761..f4cca8c 100644 --- a/Source/External/LibJPEG/jdmarker.c +++ b/Source/External/LibJPEG/jdmarker.c @@ -1,1360 +1,1360 @@ -/* - * jdmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to decode JPEG datastream markers. - * Most of the complexity arises from our desire to support input - * suspension: if not all of the data for a marker is available, - * we must exit back to the application. On resumption, we reprocess - * the marker. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* Private state */ - -typedef struct { - struct jpeg_marker_reader pub; /* public fields */ - - /* Application-overridable marker processing methods */ - jpeg_marker_parser_method process_COM; - jpeg_marker_parser_method process_APPn[16]; - - /* Limit on marker data length to save for each marker type */ - unsigned int length_limit_COM; - unsigned int length_limit_APPn[16]; - - /* Status of COM/APPn marker saving */ - jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ - unsigned int bytes_read; /* data bytes read so far in marker */ - /* Note: cur_marker is not linked into marker_list until it's all read. */ -} my_marker_reader; - -typedef my_marker_reader * my_marker_ptr; - - -/* - * Macros for fetching data from the data source module. - * - * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect - * the current restart point; we update them only when we have reached a - * suitable place to restart if a suspension occurs. - */ - -/* Declare and initialize local copies of input pointer/count */ -#define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr * datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer - -/* Unload the local copies --- do this only at a restart boundary */ -#define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) - -/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ -#define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) - -/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. - * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, - * but we must reload the local copies after a successful fill. - */ -#define MAKE_BYTE_AVAIL(cinfo,action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } - -/* Read a byte into variable V. - * If must suspend, take the specified action (typically "return FALSE"). - */ -#define INPUT_BYTE(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) - -/* As above, but read two bytes interpreted as an unsigned 16-bit integer. - * V should be declared unsigned int or perhaps INT32. - */ -#define INPUT_2BYTES(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) - - -/* - * Routines to process JPEG markers. - * - * Entry condition: JPEG marker itself has been read and its code saved - * in cinfo->unread_marker; input restart point is just after the marker. - * - * Exit: if return TRUE, have read and processed any parameters, and have - * updated the restart point to point after the parameters. - * If return FALSE, was forced to suspend before reaching end of - * marker parameters; restart point has not been moved. Same routine - * will be called again after application supplies more input data. - * - * This approach to suspension assumes that all of a marker's parameters - * can fit into a single input bufferload. This should hold for "normal" - * markers. Some COM/APPn markers might have large parameter segments - * that might not fit. If we are simply dropping such a marker, we use - * skip_input_data to get past it, and thereby put the problem on the - * source manager's shoulders. If we are saving the marker's contents - * into memory, we use a slightly different convention: when forced to - * suspend, the marker processor updates the restart point to the end of - * what it's consumed (ie, the end of the buffer) before returning FALSE. - * On resumption, cinfo->unread_marker still contains the marker code, - * but the data source will point to the next chunk of marker data. - * The marker processor must retain internal state to deal with this. - * - * Note that we don't bother to avoid duplicate trace messages if a - * suspension occurs within marker parameters. Other side effects - * require more care. - */ - - -LOCAL(boolean) -get_soi (j_decompress_ptr cinfo) -/* Process an SOI marker */ -{ - int i; - - TRACEMS(cinfo, 1, JTRC_SOI); - - if (cinfo->marker->saw_SOI) - ERREXIT(cinfo, JERR_SOI_DUPLICATE); - - /* Reset all parameters that are defined to be reset by SOI */ - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - cinfo->restart_interval = 0; - - /* Set initial assumptions for colorspace etc */ - - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ - - cinfo->saw_JFIF_marker = FALSE; - cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ - cinfo->JFIF_minor_version = 1; - cinfo->density_unit = 0; - cinfo->X_density = 1; - cinfo->Y_density = 1; - cinfo->saw_Adobe_marker = FALSE; - cinfo->Adobe_transform = 0; - - cinfo->marker->saw_SOI = TRUE; - - return TRUE; -} - - -LOCAL(boolean) -get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) -/* Process a SOFn marker */ -{ - INT32 length; - int c, ci; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - cinfo->progressive_mode = is_prog; - cinfo->arith_code = is_arith; - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); - INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); - - length -= 8; - - TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, - (int) cinfo->image_width, (int) cinfo->image_height, - cinfo->num_components); - - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_DUPLICATE); - - /* We don't support files in which the image height is initially specified */ - /* as 0 and is later redefined by DNL. As long as we have to check that, */ - /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - if (length != (cinfo->num_components * 3)) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - if (cinfo->comp_info == NULL) /* do only once, even if suspend */ - cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * SIZEOF(jpeg_component_info)); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->component_index = ci; - INPUT_BYTE(cinfo, compptr->component_id, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - compptr->h_samp_factor = (c >> 4) & 15; - compptr->v_samp_factor = (c ) & 15; - INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); - - TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); - } - - cinfo->marker->saw_SOF = TRUE; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_sos (j_decompress_ptr cinfo) -/* Process a SOS marker */ -{ - INT32 length; - int i, ci, n, c, cc; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - if (! cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOS_NO_SOF); - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ - - TRACEMS1(cinfo, 1, JTRC_SOS, n); - - if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - cinfo->comps_in_scan = n; - - /* Collect the component-spec parameters */ - - for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, cc, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (cc == compptr->component_id) - goto id_found; - } - - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); - - id_found: - - cinfo->cur_comp_info[i] = compptr; - compptr->dc_tbl_no = (c >> 4) & 15; - compptr->ac_tbl_no = (c ) & 15; - - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, - compptr->dc_tbl_no, compptr->ac_tbl_no); - } - - /* Collect the additional scan parameters Ss, Se, Ah/Al. */ - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ss = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Se = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ah = (c >> 4) & 15; - cinfo->Al = (c ) & 15; - - TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, - cinfo->Ah, cinfo->Al); - - /* Prepare to scan data & restart markers */ - cinfo->marker->next_restart_num = 0; - - /* Count another SOS marker */ - cinfo->input_scan_number++; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -#ifdef D_ARITH_CODING_SUPPORTED - -LOCAL(boolean) -get_dac (j_decompress_ptr cinfo) -/* Process a DAC marker */ -{ - INT32 length; - int index, val; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - INPUT_BYTE(cinfo, val, return FALSE); - - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_DAC, index, val); - - if (index < 0 || index >= (2*NUM_ARITH_TBLS)) - ERREXIT1(cinfo, JERR_DAC_INDEX, index); - - if (index >= NUM_ARITH_TBLS) { /* define AC table */ - cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; - } else { /* define DC table */ - cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); - cinfo->arith_dc_U[index] = (UINT8) (val >> 4); - if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) - ERREXIT1(cinfo, JERR_DAC_VALUE, val); - } - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - -#else /* ! D_ARITH_CODING_SUPPORTED */ - -#define get_dac(cinfo) skip_variable(cinfo) - -#endif /* D_ARITH_CODING_SUPPORTED */ - - -LOCAL(boolean) -get_dht (j_decompress_ptr cinfo) -/* Process a DHT marker */ -{ - INT32 length; - UINT8 bits[17]; - UINT8 huffval[256]; - int i, index, count; - JHUFF_TBL **htblptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 16) { - INPUT_BYTE(cinfo, index, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DHT, index); - - bits[0] = 0; - count = 0; - for (i = 1; i <= 16; i++) { - INPUT_BYTE(cinfo, bits[i], return FALSE); - count += bits[i]; - } - - length -= 1 + 16; - - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); - - /* Here we just do minimal validation of the counts to avoid walking - * off the end of our table space. jdhuff.c will check more carefully. - */ - if (count > 256 || ((INT32) count) > length) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - - for (i = 0; i < count; i++) - INPUT_BYTE(cinfo, huffval[i], return FALSE); - - length -= count; - - if (index & 0x10) { /* AC table definition */ - index -= 0x10; - htblptr = &cinfo->ac_huff_tbl_ptrs[index]; - } else { /* DC table definition */ - htblptr = &cinfo->dc_huff_tbl_ptrs[index]; - } - - if (index < 0 || index >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_DHT_INDEX, index); - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dqt (j_decompress_ptr cinfo) -/* Process a DQT marker */ -{ - INT32 length; - int n, i, prec; - unsigned int tmp; - JQUANT_TBL *quant_ptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, n, return FALSE); - prec = n >> 4; - n &= 0x0F; - - TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); - - if (n >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, n); - - if (cinfo->quant_tbl_ptrs[n] == NULL) - cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); - quant_ptr = cinfo->quant_tbl_ptrs[n]; - - for (i = 0; i < DCTSIZE2; i++) { - if (prec) - INPUT_2BYTES(cinfo, tmp, return FALSE); - else - INPUT_BYTE(cinfo, tmp, return FALSE); - /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; - } - - if (cinfo->err->trace_level >= 2) { - for (i = 0; i < DCTSIZE2; i += 8) { - TRACEMS8(cinfo, 2, JTRC_QUANTVALS, - quant_ptr->quantval[i], quant_ptr->quantval[i+1], - quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], - quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], - quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); - } - } - - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dri (j_decompress_ptr cinfo) -/* Process a DRI marker */ -{ - INT32 length; - unsigned int tmp; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - - if (length != 4) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_2BYTES(cinfo, tmp, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DRI, tmp); - - cinfo->restart_interval = tmp; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Routines for processing APPn and COM markers. - * These are either saved in memory or discarded, per application request. - * APP0 and APP14 are specially checked to see if they are - * JFIF and Adobe markers, respectively. - */ - -#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ -#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ -#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ - - -LOCAL(void) -examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP0. - * Take appropriate action if it is a JFIF marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - INT32 totallen = (INT32) datalen + remaining; - - if (datalen >= APP0_DATA_LEN && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x49 && - GETJOCTET(data[3]) == 0x46 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF APP0 marker: save info */ - cinfo->saw_JFIF_marker = TRUE; - cinfo->JFIF_major_version = GETJOCTET(data[5]); - cinfo->JFIF_minor_version = GETJOCTET(data[6]); - cinfo->density_unit = GETJOCTET(data[7]); - cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); - cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); - /* Check version. - * Major version must be 1, anything else signals an incompatible change. - * (We used to treat this as an error, but now it's a nonfatal warning, - * because some bozo at Hijaak couldn't read the spec.) - * Minor version should be 0..2, but process anyway if newer. - */ - if (cinfo->JFIF_major_version != 1) - WARNMS2(cinfo, JWRN_JFIF_MAJOR, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version); - /* Generate trace messages */ - TRACEMS5(cinfo, 1, JTRC_JFIF, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); - /* Validate thumbnail dimensions and issue appropriate messages */ - if (GETJOCTET(data[12]) | GETJOCTET(data[13])) - TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, - GETJOCTET(data[12]), GETJOCTET(data[13])); - totallen -= APP0_DATA_LEN; - if (totallen != - ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) - TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); - } else if (datalen >= 6 && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x58 && - GETJOCTET(data[3]) == 0x58 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF "JFXX" extension APP0 marker */ - /* The library doesn't actually do anything with these, - * but we try to produce a helpful trace message. - */ - switch (GETJOCTET(data[5])) { - case 0x10: - TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); - break; - case 0x11: - TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); - break; - case 0x13: - TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); - break; - default: - TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, - GETJOCTET(data[5]), (int) totallen); - break; - } - } else { - /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); - } -} - - -LOCAL(void) -examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP14. - * Take appropriate action if it is an Adobe marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - unsigned int version, flags0, flags1, transform; - - if (datalen >= APP14_DATA_LEN && - GETJOCTET(data[0]) == 0x41 && - GETJOCTET(data[1]) == 0x64 && - GETJOCTET(data[2]) == 0x6F && - GETJOCTET(data[3]) == 0x62 && - GETJOCTET(data[4]) == 0x65) { - /* Found Adobe APP14 marker */ - version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); - flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); - flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); - transform = GETJOCTET(data[11]); - TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); - cinfo->saw_Adobe_marker = TRUE; - cinfo->Adobe_transform = (UINT8) transform; - } else { - /* Start of APP14 does not match "Adobe", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); - } -} - - -METHODDEF(boolean) -get_interesting_appn (j_decompress_ptr cinfo) -/* Process an APP0 or APP14 marker without saving it */ -{ - INT32 length; - JOCTET b[APPN_DATA_LEN]; - unsigned int i, numtoread; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - /* get the interesting part of the marker data */ - if (length >= APPN_DATA_LEN) - numtoread = APPN_DATA_LEN; - else if (length > 0) - numtoread = (unsigned int) length; - else - numtoread = 0; - for (i = 0; i < numtoread; i++) - INPUT_BYTE(cinfo, b[i], return FALSE); - length -= numtoread; - - /* process it */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - case M_APP14: - examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - default: - /* can't get here unless jpeg_save_markers chooses wrong processor */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -#ifdef SAVE_MARKERS_SUPPORTED - -METHODDEF(boolean) -save_marker (j_decompress_ptr cinfo) -/* Save an APPn or COM marker into the marker list */ -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - jpeg_saved_marker_ptr cur_marker = marker->cur_marker; - unsigned int bytes_read, data_length; - JOCTET FAR * data; - INT32 length = 0; - INPUT_VARS(cinfo); - - if (cur_marker == NULL) { - /* begin reading a marker */ - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - if (length >= 0) { /* watch out for bogus length word */ - /* figure out how much we want to save */ - unsigned int limit; - if (cinfo->unread_marker == (int) M_COM) - limit = marker->length_limit_COM; - else - limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; - if ((unsigned int) length < limit) - limit = (unsigned int) length; - /* allocate and initialize the marker item */ - cur_marker = (jpeg_saved_marker_ptr) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(struct jpeg_marker_struct) + limit); - cur_marker->next = NULL; - cur_marker->marker = (UINT8) cinfo->unread_marker; - cur_marker->original_length = (unsigned int) length; - cur_marker->data_length = limit; - /* data area is just beyond the jpeg_marker_struct */ - data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); - marker->cur_marker = cur_marker; - marker->bytes_read = 0; - bytes_read = 0; - data_length = limit; - } else { - /* deal with bogus length word */ - bytes_read = data_length = 0; - data = NULL; - } - } else { - /* resume reading a marker */ - bytes_read = marker->bytes_read; - data_length = cur_marker->data_length; - data = cur_marker->data + bytes_read; - } - - while (bytes_read < data_length) { - INPUT_SYNC(cinfo); /* move the restart point to here */ - marker->bytes_read = bytes_read; - /* If there's not at least one byte in buffer, suspend */ - MAKE_BYTE_AVAIL(cinfo, return FALSE); - /* Copy bytes with reasonable rapidity */ - while (bytes_read < data_length && bytes_in_buffer > 0) { - *data++ = *next_input_byte++; - bytes_in_buffer--; - bytes_read++; - } - } - - /* Done reading what we want to read */ - if (cur_marker != NULL) { /* will be NULL if bogus length word */ - /* Add new marker to end of list */ - if (cinfo->marker_list == NULL) { - cinfo->marker_list = cur_marker; - } else { - jpeg_saved_marker_ptr prev = cinfo->marker_list; - while (prev->next != NULL) - prev = prev->next; - prev->next = cur_marker; - } - /* Reset pointer & calc remaining data length */ - data = cur_marker->data; - length = cur_marker->original_length - data_length; - } - /* Reset to initial state for next marker */ - marker->cur_marker = NULL; - - /* Process the marker if interesting; else just make a generic trace msg */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, data, data_length, length); - break; - case M_APP14: - examine_app14(cinfo, data, data_length, length); - break; - default: - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, - (int) (data_length + length)); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -METHODDEF(boolean) -skip_variable (j_decompress_ptr cinfo) -/* Skip over an unknown or uninteresting variable-length marker */ -{ - INT32 length; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); - - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -/* - * Find the next JPEG marker, save it in cinfo->unread_marker. - * Returns FALSE if had to suspend before reaching a marker; - * in that case cinfo->unread_marker is unchanged. - * - * Note that the result might not be a valid marker code, - * but it will never be 0 or FF. - */ - -LOCAL(boolean) -next_marker (j_decompress_ptr cinfo) -{ - int c; - INPUT_VARS(cinfo); - - for (;;) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Skip any non-FF bytes. - * This may look a bit inefficient, but it will not occur in a valid file. - * We sync after each discarded byte so that a suspending data source - * can discard the byte from its buffer. - */ - while (c != 0xFF) { - cinfo->marker->discarded_bytes++; - INPUT_SYNC(cinfo); - INPUT_BYTE(cinfo, c, return FALSE); - } - /* This loop swallows any duplicate FF bytes. Extra FFs are legal as - * pad bytes, so don't count them in discarded_bytes. We assume there - * will not be so many consecutive FF bytes as to overflow a suspending - * data source's input buffer. - */ - do { - INPUT_BYTE(cinfo, c, return FALSE); - } while (c == 0xFF); - if (c != 0) - break; /* found a valid marker, exit loop */ - /* Reach here if we found a stuffed-zero data sequence (FF/00). - * Discard it and loop back to try again. - */ - cinfo->marker->discarded_bytes += 2; - INPUT_SYNC(cinfo); - } - - if (cinfo->marker->discarded_bytes != 0) { - WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); - cinfo->marker->discarded_bytes = 0; - } - - cinfo->unread_marker = c; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -first_marker (j_decompress_ptr cinfo) -/* Like next_marker, but used to obtain the initial SOI marker. */ -/* For this marker, we do not allow preceding garbage or fill; otherwise, - * we might well scan an entire input file before realizing it ain't JPEG. - * If an application wants to process non-JFIF files, it must seek to the - * SOI before calling the JPEG library. - */ -{ - int c, c2; - INPUT_VARS(cinfo); - - INPUT_BYTE(cinfo, c, return FALSE); - INPUT_BYTE(cinfo, c2, return FALSE); - if (c != 0xFF || c2 != (int) M_SOI) - ERREXIT2(cinfo, JERR_NO_SOI, c, c2); - - cinfo->unread_marker = c2; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Read markers until SOS or EOI. - * - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - -METHODDEF(int) -read_markers (j_decompress_ptr cinfo) -{ - /* Outer loop repeats once for each marker. */ - for (;;) { - /* Collect the marker proper, unless we already did. */ - /* NB: first_marker() enforces the requirement that SOI appear first. */ - if (cinfo->unread_marker == 0) { - if (! cinfo->marker->saw_SOI) { - if (! first_marker(cinfo)) - return JPEG_SUSPENDED; - } else { - if (! next_marker(cinfo)) - return JPEG_SUSPENDED; - } - } - /* At this point cinfo->unread_marker contains the marker code and the - * input point is just past the marker proper, but before any parameters. - * A suspension will cause us to return with this state still true. - */ - switch (cinfo->unread_marker) { - case M_SOI: - if (! get_soi(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_SOF0: /* Baseline */ - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, TRUE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE)) - return JPEG_SUSPENDED; - break; - - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, TRUE, TRUE)) - return JPEG_SUSPENDED; - break; - - /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ - case M_SOF5: /* Differential sequential, Huffman */ - case M_SOF6: /* Differential progressive, Huffman */ - case M_SOF7: /* Differential lossless, Huffman */ - case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ - case M_SOF13: /* Differential sequential, arithmetic */ - case M_SOF14: /* Differential progressive, arithmetic */ - case M_SOF15: /* Differential lossless, arithmetic */ - ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); - break; - - case M_SOS: - if (! get_sos(cinfo)) - return JPEG_SUSPENDED; - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_SOS; - - case M_EOI: - TRACEMS(cinfo, 1, JTRC_EOI); - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_EOI; - - case M_DAC: - if (! get_dac(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DHT: - if (! get_dht(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DQT: - if (! get_dqt(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DRI: - if (! get_dri(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ - cinfo->unread_marker - (int) M_APP0]) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_COM: - if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_RST0: /* these are all parameterless */ - case M_RST1: - case M_RST2: - case M_RST3: - case M_RST4: - case M_RST5: - case M_RST6: - case M_RST7: - case M_TEM: - TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); - break; - - case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ - if (! skip_variable(cinfo)) - return JPEG_SUSPENDED; - break; - - default: /* must be DHP, EXP, JPGn, or RESn */ - /* For now, we treat the reserved markers as fatal errors since they are - * likely to be used to signal incompatible JPEG Part 3 extensions. - * Once the JPEG 3 version-number marker is well defined, this code - * ought to change! - */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - /* Successfully processed marker, so reset state variable */ - cinfo->unread_marker = 0; - } /* end loop */ -} - - -/* - * Read a restart marker, which is expected to appear next in the datastream; - * if the marker is not there, take appropriate recovery action. - * Returns FALSE if suspension is required. - * - * This is called by the entropy decoder after it has read an appropriate - * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder - * has already read a marker from the data source. Under normal conditions - * cinfo->unread_marker will be reset to 0 before returning; if not reset, - * it holds a marker which the decoder will be unable to read past. - */ - -METHODDEF(boolean) -read_restart_marker (j_decompress_ptr cinfo) -{ - /* Obtain a marker unless we already did. */ - /* Note that next_marker will complain if it skips any data. */ - if (cinfo->unread_marker == 0) { - if (! next_marker(cinfo)) - return FALSE; - } - - if (cinfo->unread_marker == - ((int) M_RST0 + cinfo->marker->next_restart_num)) { - /* Normal case --- swallow the marker and let entropy decoder continue */ - TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); - cinfo->unread_marker = 0; - } else { - /* Uh-oh, the restart markers have been messed up. */ - /* Let the data source manager determine how to resync. */ - if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) - return FALSE; - } - - /* Update next-restart state */ - cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; - - return TRUE; -} - - -/* - * This is the default resync_to_restart method for data source managers - * to use if they don't have any better approach. Some data source managers - * may be able to back up, or may have additional knowledge about the data - * which permits a more intelligent recovery strategy; such managers would - * presumably supply their own resync method. - * - * read_restart_marker calls resync_to_restart if it finds a marker other than - * the restart marker it was expecting. (This code is *not* used unless - * a nonzero restart interval has been declared.) cinfo->unread_marker is - * the marker code actually found (might be anything, except 0 or FF). - * The desired restart marker number (0..7) is passed as a parameter. - * This routine is supposed to apply whatever error recovery strategy seems - * appropriate in order to position the input stream to the next data segment. - * Note that cinfo->unread_marker is treated as a marker appearing before - * the current data-source input point; usually it should be reset to zero - * before returning. - * Returns FALSE if suspension is required. - * - * This implementation is substantially constrained by wanting to treat the - * input as a data stream; this means we can't back up. Therefore, we have - * only the following actions to work with: - * 1. Simply discard the marker and let the entropy decoder resume at next - * byte of file. - * 2. Read forward until we find another marker, discarding intervening - * data. (In theory we could look ahead within the current bufferload, - * without having to discard data if we don't find the desired marker. - * This idea is not implemented here, in part because it makes behavior - * dependent on buffer size and chance buffer-boundary positions.) - * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). - * This will cause the entropy decoder to process an empty data segment, - * inserting dummy zeroes, and then we will reprocess the marker. - * - * #2 is appropriate if we think the desired marker lies ahead, while #3 is - * appropriate if the found marker is a future restart marker (indicating - * that we have missed the desired restart marker, probably because it got - * corrupted). - * We apply #2 or #3 if the found marker is a restart marker no more than - * two counts behind or ahead of the expected one. We also apply #2 if the - * found marker is not a legal JPEG marker code (it's certainly bogus data). - * If the found marker is a restart marker more than 2 counts away, we do #1 - * (too much risk that the marker is erroneous; with luck we will be able to - * resync at some future point). - * For any valid non-restart JPEG marker, we apply #3. This keeps us from - * overrunning the end of a scan. An implementation limited to single-scan - * files might find it better to apply #2 for markers other than EOI, since - * any other marker would have to be bogus data in that case. - */ - -GLOBAL(boolean) -jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) -{ - int marker = cinfo->unread_marker; - int action = 1; - - /* Always put up a warning. */ - WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - - /* Outer loop handles repeated decision after scanning forward. */ - for (;;) { - if (marker < (int) M_SOF0) - action = 2; /* invalid marker */ - else if (marker < (int) M_RST0 || marker > (int) M_RST7) - action = 3; /* valid non-restart marker */ - else { - if (marker == ((int) M_RST0 + ((desired+1) & 7)) || - marker == ((int) M_RST0 + ((desired+2) & 7))) - action = 3; /* one of the next two expected restarts */ - else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) - action = 2; /* a prior restart, so advance */ - else - action = 1; /* desired restart or too far away */ - } - TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); - switch (action) { - case 1: - /* Discard marker and let entropy decoder resume processing. */ - cinfo->unread_marker = 0; - return TRUE; - case 2: - /* Scan to the next marker, and repeat the decision loop. */ - if (! next_marker(cinfo)) - return FALSE; - marker = cinfo->unread_marker; - break; - case 3: - /* Return without advancing past this marker. */ - /* Entropy decoder will be forced to process an empty segment. */ - return TRUE; - } - } /* end loop */ -} - - -/* - * Reset marker processing state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - cinfo->comp_info = NULL; /* until allocated by get_sof */ - cinfo->input_scan_number = 0; /* no SOS seen yet */ - cinfo->unread_marker = 0; /* no pending marker */ - marker->pub.saw_SOI = FALSE; /* set internal state too */ - marker->pub.saw_SOF = FALSE; - marker->pub.discarded_bytes = 0; - marker->cur_marker = NULL; -} - - -/* - * Initialize the marker reader module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker; - int i; - - /* Create subobject in permanent pool */ - marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_marker_reader)); - cinfo->marker = (struct jpeg_marker_reader *) marker; - /* Initialize public method pointers */ - marker->pub.reset_marker_reader = reset_marker_reader; - marker->pub.read_markers = read_markers; - marker->pub.read_restart_marker = read_restart_marker; - /* Initialize COM/APPn processing. - * By default, we examine and then discard APP0 and APP14, - * but simply discard COM and all other APPn. - */ - marker->process_COM = skip_variable; - marker->length_limit_COM = 0; - for (i = 0; i < 16; i++) { - marker->process_APPn[i] = skip_variable; - marker->length_limit_APPn[i] = 0; - } - marker->process_APPn[0] = get_interesting_appn; - marker->process_APPn[14] = get_interesting_appn; - /* Reset marker processing state */ - reset_marker_reader(cinfo); -} - - -/* - * Control saving of COM and APPn markers into marker_list. - */ - -#ifdef SAVE_MARKERS_SUPPORTED - -GLOBAL(void) -jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - long maxlength; - jpeg_marker_parser_method processor; - - /* Length limit mustn't be larger than what we can allocate - * (should only be a concern in a 16-bit environment). - */ - maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); - if (((long) length_limit) > maxlength) - length_limit = (unsigned int) maxlength; - - /* Choose processor routine to use. - * APP0/APP14 have special requirements. - */ - if (length_limit) { - processor = save_marker; - /* If saving APP0/APP14, save at least enough for our internal use. */ - if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) - length_limit = APP0_DATA_LEN; - else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) - length_limit = APP14_DATA_LEN; - } else { - processor = skip_variable; - /* If discarding APP0/APP14, use our regular on-the-fly processor. */ - if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) - processor = get_interesting_appn; - } - - if (marker_code == (int) M_COM) { - marker->process_COM = processor; - marker->length_limit_COM = length_limit; - } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { - marker->process_APPn[marker_code - (int) M_APP0] = processor; - marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; - } else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -/* - * Install a special processing method for COM or APPn markers. - */ - -GLOBAL(void) -jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - if (marker_code == (int) M_COM) - marker->process_COM = routine; - else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) - marker->process_APPn[marker_code - (int) M_APP0] = routine; - else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->progressive_mode = is_prog; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, index, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, index, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, index); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } + + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + INT32 totallen = (INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, TRUE, TRUE)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/Source/External/LibJPEG/jdmaster.c b/Source/External/LibJPEG/jdmaster.c index eda4b3f..2802c5b 100644 --- a/Source/External/LibJPEG/jdmaster.c +++ b/Source/External/LibJPEG/jdmaster.c @@ -1,557 +1,557 @@ -/* - * jdmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG decompressor. - * These routines are concerned with selecting the modules to be executed - * and with determining the number of passes and the work to be done in each - * pass. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_decomp_master pub; /* public fields */ - - int pass_number; /* # of passes completed */ - - boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ - - /* Saved references to initialized quantizer modules, - * in case we need to switch modes. - */ - struct jpeg_color_quantizer * quantizer_1pass; - struct jpeg_color_quantizer * quantizer_2pass; -} my_decomp_master; - -typedef my_decomp_master * my_master_ptr; - - -/* - * Determine whether merged upsample/color conversion should be used. - * CRUCIAL: this must match the actual capabilities of jdmerge.c! - */ - -LOCAL(boolean) -use_merged_upsample (j_decompress_ptr cinfo) -{ -#ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ - if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) - return FALSE; - /* jdmerge.c only supports YCC=>RGB color conversion */ - if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || - cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) - return FALSE; - /* and it only handles 2h1v or 2h2v sampling ratios */ - if (cinfo->comp_info[0].h_samp_factor != 2 || - cinfo->comp_info[1].h_samp_factor != 1 || - cinfo->comp_info[2].h_samp_factor != 1 || - cinfo->comp_info[0].v_samp_factor > 2 || - cinfo->comp_info[1].v_samp_factor != 1 || - cinfo->comp_info[2].v_samp_factor != 1) - return FALSE; - /* furthermore, it doesn't work if we've scaled the IDCTs differently */ - if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) - return FALSE; - /* ??? also need to test for upsample-time rescaling, when & if supported */ - return TRUE; /* by golly, it'll work... */ -#else - return FALSE; -#endif -} - - -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - * Also note that it may be called before the master module is initialized! - */ - -GLOBAL(void) -jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; -#endif - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_READY) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - -#ifdef IDCT_SCALING_SUPPORTED - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_DCT_scaled_size = 1; - } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_DCT_scaled_size = 2; - } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_DCT_scaled_size = 4; - } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_DCT_scaled_size = DCTSIZE; - } - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->min_DCT_scaled_size; - while (ssize < DCTSIZE && - (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && - (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { - ssize = ssize * 2; - } - compptr->DCT_scaled_size = ssize; - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ - - /* Report number of components in selected colorspace. */ - /* Probably this should be in the color conversion module... */ - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - break; - case JCS_RGB: -#if RGB_PIXELSIZE != 3 - cinfo->out_color_components = RGB_PIXELSIZE; - break; -#endif /* else share code with YCbCr */ - case JCS_YCbCr: - cinfo->out_color_components = 3; - break; - case JCS_CMYK: - case JCS_YCCK: - cinfo->out_color_components = 4; - break; - default: /* else must be same colorspace as in file */ - cinfo->out_color_components = cinfo->num_components; - break; - } - cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); - - /* See if upsampler will want to emit more than one row at a time */ - if (use_merged_upsample(cinfo)) - cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; - else - cinfo->rec_outbuf_height = 1; -} - - -/* - * Several decompression processes need to range-limit values to the range - * 0..MAXJSAMPLE; the input value may fall somewhat outside this range - * due to noise introduced by quantization, roundoff error, etc. These - * processes are inner loops and need to be as fast as possible. On most - * machines, particularly CPUs with pipelines or instruction prefetch, - * a (subscript-check-less) C table lookup - * x = sample_range_limit[x]; - * is faster than explicit tests - * if (x < 0) x = 0; - * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; - * These processes all use a common table prepared by the routine below. - * - * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing - * off the end of memory and getting a bad-pointer trap, we perform the - * post-IDCT limiting thus: - * x = range_limit[x & MASK]; - * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit - * samples. Under normal circumstances this is more than enough range and - * a correct output will be generated; with bogus input data the mask will - * cause wraparound, and we will safely generate a bogus-but-in-range output. - * For the post-IDCT step, we want to convert the data from signed to unsigned - * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. - * - * Note that the table is allocated in near data space on PCs; it's small - * enough and used often enough to justify this. - */ - -LOCAL(void) -prepare_range_limit_table (j_decompress_ptr cinfo) -/* Allocate and fill in the sample_range_limit table */ -{ - JSAMPLE * table; - int i; - - table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ - cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - MEMZERO(table + (2 * (MAXJSAMPLE+1)), - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); -} - - -/* - * Master selection of decompression modules. - * This is done once at jpeg_start_decompress time. We determine - * which modules will be used and give them appropriate initialization calls. - * We also initialize the decompressor input side to begin consuming data. - * - * Since jpeg_read_header has finished, we know what is in the SOF - * and (first) SOS markers. We also have all the application parameter - * settings. - */ - -LOCAL(void) -master_selection (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - boolean use_c_buffer; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* Initialize dimensions and other stuff */ - jpeg_calc_output_dimensions(cinfo); - prepare_range_limit_table(cinfo); - - /* Width of an output scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* Initialize my private state */ - master->pass_number = 0; - master->using_merged_upsample = use_merged_upsample(cinfo); - - /* Color quantizer selection */ - master->quantizer_1pass = NULL; - master->quantizer_2pass = NULL; - /* No mode changes if not using buffered-image mode. */ - if (! cinfo->quantize_colors || ! cinfo->buffered_image) { - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - } - if (cinfo->quantize_colors) { - if (cinfo->raw_data_out) - ERREXIT(cinfo, JERR_NOTIMPL); - /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { - cinfo->enable_1pass_quant = TRUE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - cinfo->colormap = NULL; - } else if (cinfo->colormap != NULL) { - cinfo->enable_external_quant = TRUE; - } else if (cinfo->two_pass_quantize) { - cinfo->enable_2pass_quant = TRUE; - } else { - cinfo->enable_1pass_quant = TRUE; - } - - if (cinfo->enable_1pass_quant) { -#ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); - master->quantizer_1pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - - /* We use the 2-pass code to map to external colormaps. */ - if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { -#ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); - master->quantizer_2pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - /* If both quantizers are initialized, the 2-pass one is left active; - * this is necessary for starting with quantization to an external map. - */ - } - - /* Post-processing: in particular, color conversion first */ - if (! cinfo->raw_data_out) { - if (master->using_merged_upsample) { -#ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); - } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - if (! cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* If jpeg_start_decompress will read the whole file, initialize - * progress monitoring appropriately. The input step is counted - * as one pass. - */ - if (cinfo->progress != NULL && ! cinfo->buffered_image && - cinfo->inputctl->has_multiple_scans) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); - /* Count the input pass as done */ - master->pass_number++; - } -#endif /* D_MULTISCAN_FILES_SUPPORTED */ -} - - -/* - * Per-pass setup. - * This is called at the beginning of each output pass. We determine which - * modules will be active during this pass and give them appropriate - * start_pass calls. We also set is_dummy_pass to indicate whether this - * is a "real" output pass or a dummy pass for color quantization. - * (In the latter case, jdapistd.c will crank the pass to completion.) - */ - -METHODDEF(void) -prepare_for_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (master->pub.is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Final pass of 2-pass quantization */ - master->pub.is_dummy_pass = FALSE; - (*cinfo->cquantize->start_pass) (cinfo, FALSE); - (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); - (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - if (cinfo->quantize_colors && cinfo->colormap == NULL) { - /* Select new quantization method */ - if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { - cinfo->cquantize = master->quantizer_2pass; - master->pub.is_dummy_pass = TRUE; - } else if (cinfo->enable_1pass_quant) { - cinfo->cquantize = master->quantizer_1pass; - } else { - ERREXIT(cinfo, JERR_MODE_CHANGE); - } - } - (*cinfo->idct->start_pass) (cinfo); - (*cinfo->coef->start_output_pass) (cinfo); - if (! cinfo->raw_data_out) { - if (! master->using_merged_upsample) - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->upsample->start_pass) (cinfo); - if (cinfo->quantize_colors) - (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); - (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - } - } - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); - /* In buffered-image mode, we assume one more output pass if EOI not - * yet reached, but no more passes if EOI has been reached. - */ - if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { - cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); - } - } -} - - -/* - * Finish up at end of an output pass. - */ - -METHODDEF(void) -finish_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (cinfo->quantize_colors) - (*cinfo->cquantize->finish_pass) (cinfo); - master->pass_number++; -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Switch to a new external colormap between output passes. - */ - -GLOBAL(void) -jpeg_new_colormap (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_BUFIMAGE) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (cinfo->quantize_colors && cinfo->enable_external_quant && - cinfo->colormap != NULL) { - /* Select 2-pass quantizer for external colormap use */ - cinfo->cquantize = master->quantizer_2pass; - /* Notify quantizer of colormap change */ - (*cinfo->cquantize->new_color_map) (cinfo); - master->pub.is_dummy_pass = FALSE; /* just in case */ - } else - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -/* - * Initialize master decompression control and select active modules. - * This is performed at the start of jpeg_start_decompress. - */ - -GLOBAL(void) -jinit_master_decompress (j_decompress_ptr cinfo) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_decomp_master)); - cinfo->master = (struct jpeg_decomp_master *) master; - master->pub.prepare_for_output_pass = prepare_for_output_pass; - master->pub.finish_output_pass = finish_output_pass; - - master->pub.is_dummy_pass = FALSE; - - master_selection(cinfo); -} +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + +#ifdef IDCT_SCALING_SUPPORTED + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_DCT_scaled_size = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_DCT_scaled_size = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_scaled_size = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_DCT_scaled_size = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_DCT_scaled_size; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + ssize = ssize * 2; + } + compptr->DCT_scaled_size = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/Source/External/LibJPEG/jdmerge.c b/Source/External/LibJPEG/jdmerge.c index 9e3a595..3744446 100644 --- a/Source/External/LibJPEG/jdmerge.c +++ b/Source/External/LibJPEG/jdmerge.c @@ -1,400 +1,400 @@ -/* - * jdmerge.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains code for merged upsampling/color conversion. - * - * This file combines functions from jdsample.c and jdcolor.c; - * read those files first to understand what's going on. - * - * When the chroma components are to be upsampled by simple replication - * (ie, box filtering), we can save some work in color conversion by - * calculating all the output pixels corresponding to a pair of chroma - * samples at one time. In the conversion equations - * R = Y + K1 * Cr - * G = Y + K2 * Cb + K3 * Cr - * B = Y + K4 * Cb - * only the Y term varies among the group of pixels corresponding to a pair - * of chroma samples, so the rest of the terms can be calculated just once. - * At typical sampling ratios, this eliminates half or three-quarters of the - * multiplications needed for color conversion. - * - * This file currently provides implementations for the following cases: - * YCbCr => RGB color conversion only. - * Sampling ratios of 2h1v or 2h2v. - * No scaling needed at upsample time. - * Corner-aligned (non-CCIR601) sampling alignment. - * Other special cases could be added, but in most applications these are - * the only common cases. (For uncommon cases we fall back on the more - * general code in jdsample.c and jdcolor.c.) - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef UPSAMPLE_MERGING_SUPPORTED - - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Pointer to routine to do actual upsampling/conversion of one row group */ - JMETHOD(void, upmethod, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf)); - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ - - /* For 2:1 vertical sampling, we produce two output rows at a time. - * We need a "spare" row buffer to hold the second output row if the - * application provides just a one-row buffer; we also use the spare - * to discard the dummy last row if the image height is odd. - */ - JSAMPROW spare_row; - boolean spare_full; /* T if spare buffer is occupied */ - - JDIMENSION out_row_width; /* samples per output row */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. - * This is taken directly from jdcolor.c; see that file for more info. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int i; - INT32 x; - SHIFT_TEMPS - - upsample->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - upsample->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; - } -} - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_merged_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the spare buffer empty */ - upsample->spare_full = FALSE; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * The control routine just handles the row buffering considerations. - */ - -METHODDEF(void) -merged_2v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 2:1 vertical sampling case: may need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPROW work_ptrs[2]; - JDIMENSION num_rows; /* number of rows returned to caller */ - - if (upsample->spare_full) { - /* If we have a spare row saved from a previous cycle, just return it. */ - jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, - 1, upsample->out_row_width); - num_rows = 1; - upsample->spare_full = FALSE; - } else { - /* Figure number of rows to return to caller. */ - num_rows = 2; - /* Not more than the distance to the end of the image. */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - /* Create output pointer array for upsampler. */ - work_ptrs[0] = output_buf[*out_row_ctr]; - if (num_rows > 1) { - work_ptrs[1] = output_buf[*out_row_ctr + 1]; - } else { - work_ptrs[1] = upsample->spare_row; - upsample->spare_full = TRUE; - } - /* Now do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); - } - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (! upsample->spare_full) - (*in_row_group_ctr)++; -} - - -METHODDEF(void) -merged_1v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 1:1 vertical sampling case: much easier, never need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Just do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, - output_buf + *out_row_ctr); - /* Adjust counts */ - (*out_row_ctr)++; - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by the control routines to do - * the actual upsampling/conversion. One row group is processed per call. - * - * Note: since we may be writing directly into application-supplied buffers, - * we have to be honest about the output width; we can't assume the buffer - * has been rounded up to an even width. - */ - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. - */ - -METHODDEF(void) -h2v1_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr0 = input_buf[0][in_row_group_ctr]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr = output_buf[0]; - /* Loop for each pair of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 2 Y values and emit 2 pixels */ - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. - */ - -METHODDEF(void) -h2v2_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr00 = input_buf[0][in_row_group_ctr*2]; - inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr0 = output_buf[0]; - outptr1 = output_buf[1]; - /* Loop for each group of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 4 Y values and emit 4 pixels */ - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Module initialization routine for merged upsampling/color conversion. - * - * NB: this is called under the conditions determined by use_merged_upsample() - * in jdmaster.c. That routine MUST correspond to the actual capabilities - * of this module; no safety checks are made here. - */ - -GLOBAL(void) -jinit_merged_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; - upsample->pub.start_pass = start_pass_merged_upsample; - upsample->pub.need_context_rows = FALSE; - - upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; - - if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; - upsample->upmethod = h2v2_merged_upsample; - /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); - } else { - upsample->pub.upsample = merged_1v_upsample; - upsample->upmethod = h2v1_merged_upsample; - /* No spare row needed */ - upsample->spare_row = NULL; - } - - build_ycc_rgb_table(cinfo); -} - -#endif /* UPSAMPLE_MERGING_SUPPORTED */ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/Source/External/LibJPEG/jdphuff.c b/Source/External/LibJPEG/jdphuff.c index 2404743..2267809 100644 --- a/Source/External/LibJPEG/jdphuff.c +++ b/Source/External/LibJPEG/jdphuff.c @@ -1,668 +1,668 @@ -/* - * jdphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for progressive JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdhuff.c */ - - -#ifdef D_PROGRESSIVE_SUPPORTED - -/* - * Expanded entropy decoder object for progressive Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ -} phuff_entropy_decoder; - -typedef phuff_entropy_decoder * phuff_entropy_ptr; - -/* Forward declarations */ -METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band, bad; - int ci, coefi, tbl; - int *coef_bit_ptr; - jpeg_component_info * compptr; - - is_DC_band = (cinfo->Ss == 0); - - /* Validate scan parameters */ - bad = FALSE; - if (is_DC_band) { - if (cinfo->Se != 0) - bad = TRUE; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) - bad = TRUE; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - bad = TRUE; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Al != cinfo->Ah-1) - bad = TRUE; - } - if (cinfo->Al > 13) /* need not check for < 0 */ - bad = TRUE; - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ - if (bad) - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int cindex = cinfo->cur_comp_info[ci]->component_index; - coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (is_DC_band) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; - - /* Initialize private state variables */ - entropy->saved.EOBRUN = 0; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ - entropy->saved.EOBRUN = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Al = cinfo->Al; - register int s, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * tbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int Al = cinfo->Al; - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - - if (EOBRUN > 0) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r == 15) { /* ZRL */ - k += 15; /* skip 15 zeroes in band */ - } else { /* EOBr, run length is 2^r + appended bits */ - EOBRUN = 1 << r; - if (r) { /* EOBr, r > 0 */ - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - } - EOBRUN--; /* this band is processed at this moment */ - break; /* force end-of-band */ - } - } - } - - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int blkn; - JBLOCKROW block; - BITREAD_STATE_VARS; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - (*block)[0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - JCOEFPTR thiscoef; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - int num_newnz; - int newnz_pos[DCTSIZE2]; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, don't modify the MCU. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; - - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; - - if (EOBRUN == 0) { - for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = jpeg_natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - } - } - - if (EOBRUN > 0) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - for (; k <= Se; k++) { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - } - /* Count one block completed in EOB run */ - EOBRUN--; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; - -undoit: - /* Re-zero any output coefficients that we made newly nonzero */ - while (num_newnz > 0) - (*block)[newnz_pos[--num_newnz]] = 0; - - return FALSE; -} - - -/* - * Module initialization routine for progressive Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int *coef_bit_ptr; - int ci, i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_phuff_decoder; - - /* Mark derived tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } - - /* Create progression status table */ - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; -} - -#endif /* D_PROGRESSIVE_SUPPORTED */ +/* + * jdphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdhuff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Expanded entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/Source/External/LibJPEG/jdpostct.c b/Source/External/LibJPEG/jdpostct.c index 7ba9eed..571563d 100644 --- a/Source/External/LibJPEG/jdpostct.c +++ b/Source/External/LibJPEG/jdpostct.c @@ -1,290 +1,290 @@ -/* - * jdpostct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the decompression postprocessing controller. - * This controller manages the upsampling, color conversion, and color - * quantization/reduction steps; specifically, it controls the buffering - * between upsample/color conversion and color quantization/reduction. - * - * If no color quantization/reduction is required, then this module has no - * work to do, and it just hands off to the upsample/color conversion code. - * An integrated upsample/convert/quantize process would replace this module - * entirely. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_post_controller pub; /* public fields */ - - /* Color quantization source buffer: this holds output data from - * the upsample/color conversion step to be passed to the quantizer. - * For two-pass color quantization, we need a full-image buffer; - * for one-pass operation, a strip buffer is sufficient. - */ - jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ - JDIMENSION strip_height; /* buffer size in rows */ - /* for two-pass mode only: */ - JDIMENSION starting_row; /* row # of first row in current strip */ - JDIMENSION next_row; /* index of next row to fill/empty in strip */ -} my_post_controller; - -typedef my_post_controller * my_post_ptr; - - -/* Forward declarations */ -METHODDEF(void) post_process_1pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) post_process_prepass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -METHODDEF(void) post_process_2pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->quantize_colors) { - /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; - /* We could be doing buffered-image output before starting a 2-pass - * color quantization; in that case, jinit_d_post_controller did not - * allocate a strip buffer. Use the virtual-array buffer as workspace. - */ - if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - (JDIMENSION) 0, post->strip_height, TRUE); - } - } else { - /* For single-pass processing without color quantization, - * I have no work to do; just call the upsampler directly. - */ - post->pub.post_process_data = cinfo->upsample->upsample; - } - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_SAVE_AND_PASS: - /* First pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; - break; - case JBUF_CRANK_DEST: - /* Second pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; - break; -#endif /* QUANT_2PASS_SUPPORTED */ - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } - post->starting_row = post->next_row = 0; -} - - -/* - * Process some data in the one-pass (strip buffer) case. - * This is used for color precision reduction as well as one-pass quantization. - */ - -METHODDEF(void) -post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Fill the buffer, but not more than what we can dump out in one go. */ - /* Note we rely on the upsampler to detect bottom of image. */ - max_rows = out_rows_avail - *out_row_ctr; - if (max_rows > post->strip_height) - max_rows = post->strip_height; - num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &num_rows, max_rows); - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer, output_buf + *out_row_ctr, (int) num_rows); - *out_row_ctr += num_rows; -} - - -#ifdef QUANT_2PASS_SUPPORTED - -/* - * Process some data in the first pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION old_next_row, num_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, TRUE); - } - - /* Upsample some data (up to a strip height's worth). */ - old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &post->next_row, post->strip_height); - - /* Allow quantizer to scan new data. No data is emitted, */ - /* but we advance out_row_ctr so outer loop can tell when we're done. */ - if (post->next_row > old_next_row) { - num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY) NULL, (int) num_rows); - *out_row_ctr += num_rows; - } - - /* Advance if we filled the strip. */ - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - - -/* - * Process some data in the second pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, FALSE); - } - - /* Determine number of rows to emit. */ - num_rows = post->strip_height - post->next_row; /* available in strip */ - max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ - if (num_rows > max_rows) - num_rows = max_rows; - /* We have to check bottom of image here, can't depend on upsampler. */ - max_rows = cinfo->output_height - post->starting_row; - if (num_rows > max_rows) - num_rows = max_rows; - - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer + post->next_row, output_buf + *out_row_ctr, - (int) num_rows); - *out_row_ctr += num_rows; - - /* Advance if we filled the strip. */ - post->next_row += num_rows; - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize postprocessing controller. - */ - -GLOBAL(void) -jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_post_ptr post; - - post = (my_post_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_post_controller)); - cinfo->post = (struct jpeg_d_post_controller *) post; - post->pub.start_pass = start_pass_dpost; - post->whole_image = NULL; /* flag for no virtual arrays */ - post->buffer = NULL; /* flag for no strip buffer */ - - /* Create the quantization buffer, if needed */ - if (cinfo->quantize_colors) { - /* The buffer strip height is max_v_samp_factor, which is typically - * an efficient number of rows for upsampling to return. - * (In the presence of output rescaling, we might want to be smarter?) - */ - post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; - if (need_full_buffer) { - /* Two-pass color quantization: need full-image storage. */ - /* We round up the number of rows to a multiple of the strip height. */ -#ifdef QUANT_2PASS_SUPPORTED - post->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - cinfo->output_width * cinfo->out_color_components, - (JDIMENSION) jround_up((long) cinfo->output_height, - (long) post->strip_height), - post->strip_height); -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->out_color_components, - post->strip_height); - } - } -} +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/Source/External/LibJPEG/jdsample.c b/Source/External/LibJPEG/jdsample.c index e0d9040..80ffefb 100644 --- a/Source/External/LibJPEG/jdsample.c +++ b/Source/External/LibJPEG/jdsample.c @@ -1,478 +1,478 @@ -/* - * jdsample.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains upsampling routines. - * - * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. Upsampling will normally produce - * max_v_samp_factor pixel rows from each row group (but this could vary - * if the upsampler is applying a scale factor of its own). - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to upsample a single component */ -typedef JMETHOD(void, upsample1_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Color conversion buffer. When using separate upsampling and color - * conversion steps, this buffer holds one upsampled row group until it - * has been color converted and output. - * Note: we do not allocate any storage for component(s) which are full-size, - * ie do not need rescaling. The corresponding entry of color_buf[] is - * simply set to point to the input data array, thereby avoiding copying. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - /* Per-component upsampling method pointers */ - upsample1_ptr methods[MAX_COMPONENTS]; - - int next_row_out; /* counts rows emitted from color_buf */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ - - /* Height of an input row group for each component. */ - int rowgroup_height[MAX_COMPONENTS]; - - /* These arrays save pixel expansion factors so that int_expand need not - * recompute them each time. They are unused for other upsampling methods. - */ - UINT8 h_expand[MAX_COMPONENTS]; - UINT8 v_expand[MAX_COMPONENTS]; -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the conversion buffer empty */ - upsample->next_row_out = cinfo->max_v_samp_factor; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * In this version we upsample each component independently. - * We upsample one row group into the conversion buffer, then apply - * color conversion a row at a time. - */ - -METHODDEF(void) -sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int ci; - jpeg_component_info * compptr; - JDIMENSION num_rows; - - /* Fill the conversion buffer, if it's empty */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Invoke per-component upsample method. Notice we pass a POINTER - * to color_buf[ci], so that fullsize_upsample can change it. - */ - (*upsample->methods[ci]) (cinfo, compptr, - input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), - upsample->color_buf + ci); - } - upsample->next_row_out = 0; - } - - /* Color-convert and emit rows */ - - /* How many we have in the buffer: */ - num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); - /* Not more than the distance to the end of the image. Need this test - * in case the image height is not a multiple of max_v_samp_factor: - */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - upsample->next_row_out += num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by sep_upsample to upsample pixel values - * of a single component. One row group is processed per call. - */ - - -/* - * For full-size components, we just make color_buf[ci] point at the - * input buffer, and thus avoid copying any data. Note that this is - * safe only because sep_upsample doesn't declare the input row group - * "consumed" until we are done color converting and emitting it. - */ - -METHODDEF(void) -fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = input_data; -} - - -/* - * This is a no-op version used for "uninteresting" components. - * These components will not be referenced by color conversion. - */ - -METHODDEF(void) -noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = NULL; /* safety check */ -} - - -/* - * This version handles any integral sampling ratios. - * This is not used for typical JPEG files, so it need not be fast. - * Nor, for that matter, is it particularly accurate: the algorithm is - * simple replication of the input pixel onto the corresponding output - * pixels. The hi-falutin sampling literature refers to this as a - * "box filter". A box filter tends to introduce visible artifacts, - * so if you are actually going to use 3:1 or 4:1 sampling ratios - * you would be well advised to improve this code. - */ - -METHODDEF(void) -int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - register int h; - JSAMPROW outend; - int h_expand, v_expand; - int inrow, outrow; - - h_expand = upsample->h_expand[compptr->component_index]; - v_expand = upsample->v_expand[compptr->component_index]; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - /* Generate one output row with proper horizontal expansion */ - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - for (h = h_expand; h > 0; h--) { - *outptr++ = invalue; - } - } - /* Generate any additional output rows by duplicating the first one */ - if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - v_expand-1, cinfo->output_width); - } - inrow++; - outrow += v_expand; - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow, outrow; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); - inrow++; - outrow += 2; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register int invalue; - register JDIMENSION colctr; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } - - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - -METHODDEF(void) -h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; -#if BITS_IN_JSAMPLE == 8 - register int thiscolsum, lastcolsum, nextcolsum; -#else - register INT32 thiscolsum, lastcolsum, nextcolsum; -#endif - register JDIMENSION colctr; - int inrow, outrow, v; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ - inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ - inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; - - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } - - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; - } -} - - -/* - * Module initialization routine for upsampling. - */ - -GLOBAL(void) -jinit_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - int ci; - jpeg_component_info * compptr; - boolean need_buffer, do_fancy; - int h_in_group, v_in_group, h_out_group, v_out_group; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; - upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; - upsample->pub.need_context_rows = FALSE; /* until we find out differently */ - - if (cinfo->CCIR601_sampling) /* this isn't supported */ - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, - * so don't ask for it. - */ - do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; - - /* Verify we can handle the sampling factors, select per-component methods, - * and create storage as needed. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Compute size of an "input group" after IDCT scaling. This many samples - * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. - */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - h_out_group = cinfo->max_h_samp_factor; - v_out_group = cinfo->max_v_samp_factor; - upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; - if (! compptr->component_needed) { - /* Don't bother to upsample an uninteresting component. */ - upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { - /* Fullsize components can be processed without any work. */ - upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) - upsample->methods[ci] = h2v1_fancy_upsample; - else - upsample->methods[ci] = h2v1_upsample; - } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { - upsample->methods[ci] = h2v2_fancy_upsample; - upsample->pub.need_context_rows = TRUE; - } else - upsample->methods[ci] = h2v2_upsample; - } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { - /* Generic integral-factors upsampling method */ - upsample->methods[ci] = int_upsample; - upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); - upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } - } -} +/* + * jdsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/Source/External/LibJPEG/jdtrans.c b/Source/External/LibJPEG/jdtrans.c index 12c193c..6c0ab71 100644 --- a/Source/External/LibJPEG/jdtrans.c +++ b/Source/External/LibJPEG/jdtrans.c @@ -1,143 +1,143 @@ -/* - * jdtrans.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains library routines for transcoding decompression, - * that is, reading raw DCT coefficient arrays from an input JPEG file. - * The routines in jdapimin.c will also be needed by a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); - - -/* - * Read the coefficient arrays from a JPEG file. - * jpeg_read_header must be completed before calling this. - * - * The entire image is read into a set of virtual coefficient-block arrays, - * one per component. The return value is a pointer to the array of - * virtual-array descriptors. These can be manipulated directly via the - * JPEG memory manager, or handed off to jpeg_write_coefficients(). - * To release the memory occupied by the virtual arrays, call - * jpeg_finish_decompress() when done with the data. - * - * An alternative usage is to simply obtain access to the coefficient arrays - * during a buffered-image-mode decompression operation. This is allowed - * after any jpeg_finish_output() call. The arrays can be accessed until - * jpeg_finish_decompress() is called. (Note that any call to the library - * may reposition the arrays, so don't rely on access_virt_barray() results - * to stay valid across library calls.) - * - * Returns NULL if suspended. This case need be checked only if - * a suspending data source is used. - */ - -GLOBAL(jvirt_barray_ptr *) -jpeg_read_coefficients (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize active modules */ - transdecode_master_selection(cinfo); - cinfo->global_state = DSTATE_RDCOEFS; - } - if (cinfo->global_state == DSTATE_RDCOEFS) { - /* Absorb whole file into the coef buffer */ - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return NULL; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* startup underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } - /* Set state so that jpeg_finish_decompress does the right thing */ - cinfo->global_state = DSTATE_STOPPING; - } - /* At this point we should be in state DSTATE_STOPPING if being used - * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access - * to the coefficients during a full buffered-image-mode decompression. - */ - if ((cinfo->global_state == DSTATE_STOPPING || - cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { - return cinfo->coef->coef_arrays; - } - /* Oops, improper usage */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return NULL; /* keep compiler happy */ -} - - -/* - * Master selection of decompression modules for transcoding. - * This substitutes for jdmaster.c's initialization of the full decompressor. - */ - -LOCAL(void) -transdecode_master_selection (j_decompress_ptr cinfo) -{ - /* This is effectively a buffered-image operation. */ - cinfo->buffered_image = TRUE; - - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Always get a full-image coefficient buffer. */ - jinit_d_coef_controller(cinfo, TRUE); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - - /* Initialize progress monitoring. */ - if (cinfo->progress != NULL) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else if (cinfo->inputctl->has_multiple_scans) { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } else { - nscans = 1; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = 1; - } -} +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/Source/External/LibJPEG/jerror.c b/Source/External/LibJPEG/jerror.c index c98aed7..3da7be8 100644 --- a/Source/External/LibJPEG/jerror.c +++ b/Source/External/LibJPEG/jerror.c @@ -1,252 +1,252 @@ -/* - * jerror.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains simple error-reporting and trace-message routines. - * These are suitable for Unix-like systems and others where writing to - * stderr is the right thing to do. Many applications will want to replace - * some or all of these routines. - * - * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, - * you get a Windows-specific hack to display error messages in a dialog box. - * It ain't much, but it beats dropping error messages into the bit bucket, - * which is what happens to output to stderr under most Windows C compilers. - * - * These routines are used by both the compression and decompression code. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jversion.h" -#include "jerror.h" - -#ifdef USE_WINDOWS_MESSAGEBOX -#include -#endif - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif - - -/* - * Create the message string table. - * We do this from the master message list in jerror.h by re-reading - * jerror.h with a suitable definition for macro JMESSAGE. - * The message table is made an external symbol just in case any applications - * want to refer to it directly. - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_message_table jMsgTable -#endif - -#define JMESSAGE(code,string) string , - -const char * const jpeg_std_message_table[] = { -#include "jerror.h" - NULL -}; - - -/* - * Error exit handler: must not return to caller. - * - * Applications may override this if they want to get control back after - * an error. Typically one would longjmp somewhere instead of exiting. - * The setjmp buffer can be made a private field within an expanded error - * handler object. Note that the info needed to generate an error message - * is stored in the error object, so you can generate the message now or - * later, at your convenience. - * You should make sure that the JPEG object is cleaned up (with jpeg_abort - * or jpeg_destroy) at some point. - */ - -METHODDEF(void) -error_exit (j_common_ptr cinfo) -{ - /* Always display the message */ - (*cinfo->err->output_message) (cinfo); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - - exit(EXIT_FAILURE); -} - - -/* - * Actual output of an error or trace message. - * Applications may override this method to send JPEG messages somewhere - * other than stderr. - * - * On Windows, printing to stderr is generally completely useless, - * so we provide optional code to produce an error-dialog popup. - * Most Windows applications will still prefer to override this routine, - * but if they don't, it'll do something at least marginally useful. - * - * NOTE: to use the library in an environment that doesn't support the - * C stdio library, you may have to delete the call to fprintf() entirely, - * not just not use this routine. - */ - -METHODDEF(void) -output_message (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - -#ifdef USE_WINDOWS_MESSAGEBOX - /* Display it in a message dialog box */ - MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", - MB_OK | MB_ICONERROR); -#else - /* Send it to stderr, adding a newline */ - fprintf(stderr, "%s\n", buffer); -#endif -} - - -/* - * Decide whether to emit a trace or warning message. - * msg_level is one of: - * -1: recoverable corrupt-data warning, may want to abort. - * 0: important advisory messages (always display to user). - * 1: first level of tracing detail. - * 2,3,...: successively more detailed tracing messages. - * An application might override this method if it wanted to abort on warnings - * or change the policy about which messages to display. - */ - -METHODDEF(void) -emit_message (j_common_ptr cinfo, int msg_level) -{ - struct jpeg_error_mgr * err = cinfo->err; - - if (msg_level < 0) { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if (err->num_warnings == 0 || err->trace_level >= 3) - (*err->output_message) (cinfo); - /* Always count warnings in num_warnings. */ - err->num_warnings++; - } else { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if (err->trace_level >= msg_level) - (*err->output_message) (cinfo); - } -} - - -/* - * Format a message string for the most recent JPEG error or message. - * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX - * characters. Note that no '\n' character is added to the string. - * Few applications should need to override this method. - */ - -METHODDEF(void) -format_message (j_common_ptr cinfo, char * buffer) -{ - struct jpeg_error_mgr * err = cinfo->err; - int msg_code = err->msg_code; - const char * msgtext = NULL; - const char * msgptr; - char ch; - boolean isstring; - - /* Look up message string in proper table */ - if (msg_code > 0 && msg_code <= err->last_jpeg_message) { - msgtext = err->jpeg_message_table[msg_code]; - } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { - msgtext = err->addon_message_table[msg_code - err->first_addon_message]; - } - - /* Defend against bogus message number */ - if (msgtext == NULL) { - err->msg_parm.i[0] = msg_code; - msgtext = err->jpeg_message_table[0]; - } - - /* Check for string parameter, as indicated by %s in the message text */ - isstring = FALSE; - msgptr = msgtext; - while ((ch = *msgptr++) != '\0') { - if (ch == '%') { - if (*msgptr == 's') isstring = TRUE; - break; - } - } - - /* Format the message into the passed buffer */ - if (isstring) - sprintf(buffer, msgtext, err->msg_parm.s); - else - sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); -} - - -/* - * Reset error state variables at start of a new image. - * This is called during compression startup to reset trace/error - * processing to default state, without losing any application-specific - * method pointers. An application might possibly want to override - * this method if it has additional error processing state. - */ - -METHODDEF(void) -reset_error_mgr (j_common_ptr cinfo) -{ - cinfo->err->num_warnings = 0; - /* trace_level is not reset since it is an application-supplied parameter */ - cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ -} - - -/* - * Fill in the standard error-handling methods in a jpeg_error_mgr object. - * Typical call is: - * struct jpeg_compress_struct cinfo; - * struct jpeg_error_mgr err; - * - * cinfo.err = jpeg_std_error(&err); - * after which the application may override some of the methods. - */ - -GLOBAL(struct jpeg_error_mgr *) -jpeg_std_error (struct jpeg_error_mgr * err) -{ - err->error_exit = error_exit; - err->emit_message = emit_message; - err->output_message = output_message; - err->format_message = format_message; - err->reset_error_mgr = reset_error_mgr; - - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ - - /* Initialize message table pointers */ - err->jpeg_message_table = jpeg_std_message_table; - err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; - - return err; -} +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jversion.h" +#include "jerror.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jMsgTable +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/Source/External/LibJPEG/jerror.h b/Source/External/LibJPEG/jerror.h index 79084f2..fc2fffe 100644 --- a/Source/External/LibJPEG/jerror.h +++ b/Source/External/LibJPEG/jerror.h @@ -1,291 +1,291 @@ -/* - * jerror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the JPEG library. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - * A set of error-reporting macros are defined too. Some applications using - * the JPEG library may wish to include this file to get the error codes - * and/or the macros. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef JERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* JERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ - -/* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") -JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") -JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") -JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") -JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") -JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") -JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") -JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") -JMESSAGE(JERR_BAD_LIB_VERSION, - "Wrong JPEG library version: library is %d, caller expects %d") -JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") -JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") -JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") -JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") -JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") -JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") -JMESSAGE(JERR_BAD_STRUCT_SIZE, - "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") -JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") -JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") -JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") -JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") -JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") -JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") -JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") -JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") -JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") -JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") -JMESSAGE(JERR_EMS_READ, "Read from EMS failed") -JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") -JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") -JMESSAGE(JERR_FILE_READ, "Input file read error") -JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") -JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") -JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") -JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") -JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") -JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") -JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") -JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") -JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") -JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") -JMESSAGE(JERR_NOTIMPL, "Not implemented yet") -JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") -JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") -JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") -JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") -JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") -JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") -JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") -JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") -JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") -JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") -JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") -JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") -JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") -JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") -JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") -JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") -JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") -JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") -JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") -JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") -JMESSAGE(JERR_XMS_READ, "Read from XMS failed") -JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") -JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) -JMESSAGE(JMSG_VERSION, JVERSION) -JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") -JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") -JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") -JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") -JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") -JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") -JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") -JMESSAGE(JTRC_DRI, "Define Restart Interval %u") -JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") -JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") -JMESSAGE(JTRC_EOI, "End Of Image") -JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") -JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") -JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") -JMESSAGE(JTRC_JFIF_EXTENSION, - "JFIF extension marker: type 0x%02x, length %u") -JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") -JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") -JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") -JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") -JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") -JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") -JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") -JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") -JMESSAGE(JTRC_RST, "RST%d") -JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") -JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") -JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") -JMESSAGE(JTRC_SOI, "Start of Image") -JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") -JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") -JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") -JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") -JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") -JMESSAGE(JTRC_THUMB_JPEG, - "JFIF extension marker: JPEG-compressed thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_PALETTE, - "JFIF extension marker: palette thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_RGB, - "JFIF extension marker: RGB thumbnail image, length %u") -JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") -JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") -JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") -JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") -JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") -JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") -JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") -JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") -JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") -JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") -JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") -JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTMSGCODE -} J_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE - - -#ifndef JERROR_H -#define JERROR_H - -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ -#define ERREXIT(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT3(cinfo,code,p1,p2,p3) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - -#define MAKESTMT(stuff) do { stuff } while (0) - -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ -#define WARNMS(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) - -/* Informational/debugging messages */ -#define TRACEMS(cinfo,lvl,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS1(cinfo,lvl,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS2(cinfo,lvl,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMSS(cinfo,lvl,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) - -#endif /* JERROR_H */ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/Source/External/LibJPEG/jfdctflt.c b/Source/External/LibJPEG/jfdctflt.c index 7ccfb38..79d7a00 100644 --- a/Source/External/LibJPEG/jfdctflt.c +++ b/Source/External/LibJPEG/jfdctflt.c @@ -1,168 +1,168 @@ -/* - * jfdctflt.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a floating-point implementation of the - * forward DCT (Discrete Cosine Transform). - * - * This implementation should be more accurate than either of the integer - * DCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_FLOAT_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_float (FAST_FLOAT * data) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; - FAST_FLOAT *dataptr; - int ctr; - - /* Pass 1: process rows. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; - - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; - - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/Source/External/LibJPEG/jfdctfst.c b/Source/External/LibJPEG/jfdctfst.c index 005a74f..ccb378a 100644 --- a/Source/External/LibJPEG/jfdctfst.c +++ b/Source/External/LibJPEG/jfdctfst.c @@ -1,224 +1,224 @@ -/* - * jfdctfst.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * forward DCT (Discrete Cosine Transform). - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_IFAST_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jfdctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * Again to save a few shifts, the intermediate results between pass 1 and - * pass 2 are not upscaled, but are represented only to integral precision. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#define CONST_BITS 8 - - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ -#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ -#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ -#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ -#else -#define FIX_0_382683433 FIX(0.382683433) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_707106781 FIX(0.707106781) -#define FIX_1_306562965 FIX(1.306562965) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_ifast (DCTELEM * data) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z1, z2, z3, z4, z5, z11, z13; - DCTELEM *dataptr; - int ctr; - SHIFT_TEMPS - - /* Pass 1: process rows. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_IFAST_SUPPORTED */ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/Source/External/LibJPEG/jfdctint.c b/Source/External/LibJPEG/jfdctint.c index d626927..0a78b64 100644 --- a/Source/External/LibJPEG/jfdctint.c +++ b/Source/External/LibJPEG/jfdctint.c @@ -1,283 +1,283 @@ -/* - * jfdctint.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a slow-but-accurate integer implementation of the - * forward DCT (Discrete Cosine Transform). - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_ISLOW_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D DCT step produces outputs which are a factor of sqrt(N) - * larger than the true DCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D DCT, - * because the y0 and y4 outputs need not be divided by sqrt(N). - * In the IJG code, this factor of 8 is removed by the quantization step - * (in jcdctmgr.c), NOT in this module. - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (For 12-bit sample data, the intermediate - * array is INT32 anyway.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ -#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ -#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ -#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ -#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ -#else -#define FIX_0_298631336 FIX(0.298631336) -#define FIX_0_390180644 FIX(0.390180644) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_175875602 FIX(1.175875602) -#define FIX_1_501321110 FIX(1.501321110) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_1_961570560 FIX(1.961570560) -#define FIX_2_053119869 FIX(2.053119869) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_072711026 FIX(3.072711026) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_islow (DCTELEM * data) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - DCTELEM *dataptr; - int ctr; - SHIFT_TEMPS - - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); - dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS-PASS1_BITS); - - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. - * We remove the PASS1_BITS scaling, but leave the results scaled up - * by an overall factor of 8. - */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS+PASS1_BITS); - - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, - CONST_BITS+PASS1_BITS); - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_ISLOW_SUPPORTED */ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/Source/External/LibJPEG/jidctflt.c b/Source/External/LibJPEG/jidctflt.c index 5fea54c..0188ce3 100644 --- a/Source/External/LibJPEG/jidctflt.c +++ b/Source/External/LibJPEG/jidctflt.c @@ -1,242 +1,242 @@ -/* - * jidctflt.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a floating-point implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * This implementation should be more accurate than either of the integer - * IDCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_FLOAT_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a float result. - */ - -#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL(void) -jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z5, z10, z11, z12, z13; - JCOEFPTR inptr; - FLOAT_MULT_TYPE * quantptr; - FAST_FLOAT * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = tmp0 + tmp7; - wsptr[DCTSIZE*7] = tmp0 - tmp7; - wsptr[DCTSIZE*1] = tmp1 + tmp6; - wsptr[DCTSIZE*6] = tmp1 - tmp6; - wsptr[DCTSIZE*2] = tmp2 + tmp5; - wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * And testing floats for zero is relatively expensive, so we don't bother. - */ - - /* Even part */ - - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; - - tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; - - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/Source/External/LibJPEG/jidctfst.c b/Source/External/LibJPEG/jidctfst.c index 078b8c4..dba4216 100644 --- a/Source/External/LibJPEG/jidctfst.c +++ b/Source/External/LibJPEG/jidctfst.c @@ -1,368 +1,368 @@ -/* - * jidctfst.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_IFAST_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jidctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * The dequantized coefficients are not integers because the AA&N scaling - * factors have been incorporated. We represent them scaled up by PASS1_BITS, - * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to - * avoid a descaling shift; this compromises accuracy rather drastically - * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, - * so we use a much larger scaling factor to preserve accuracy. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 8 -#define PASS1_BITS 2 -#else -#define CONST_BITS 8 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ -#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ -#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ -#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ -#else -#define FIX_1_082392200 FIX(1.082392200) -#define FIX_1_414213562 FIX(1.414213562) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_613125930 FIX(2.613125930) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 - * multiplication will do. For 12-bit data, the multiplier table is - * declared INT32, so a 32-bit multiply will be used. - */ - -#if BITS_IN_JSAMPLE == 8 -#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) -#else -#define DEQUANTIZE(coef,quantval) \ - DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) -#endif - - -/* Like DESCALE, but applies to a DCTELEM and produces an int. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS DCTELEM ishift_temp; -#if BITS_IN_JSAMPLE == 8 -#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ -#else -#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ -#endif -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -#ifdef USE_ACCURATE_ROUNDING -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) -#else -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) -#endif - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL(void) -jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z5, z10, z11, z12, z13; - JCOEFPTR inptr; - IFAST_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS /* for DESCALE */ - ISHIFT_TEMPS /* for IDESCALE */ - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); - wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); - wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); - wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); - wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); - wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); - tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); - - tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; - z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; - z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; - z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_IFAST_SUPPORTED */ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/Source/External/LibJPEG/jidctint.c b/Source/External/LibJPEG/jidctint.c index 4f47fe8..a72b320 100644 --- a/Source/External/LibJPEG/jidctint.c +++ b/Source/External/LibJPEG/jidctint.c @@ -1,389 +1,389 @@ -/* - * jidctint.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a slow-but-accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_ISLOW_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) - * larger than the true IDCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D IDCT, - * because the y0 and y4 inputs need not be divided by sqrt(N). - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (To scale up 12-bit sample data further, an - * intermediate INT32 array would be needed.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ -#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ -#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ -#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ -#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ -#else -#define FIX_0_298631336 FIX(0.298631336) -#define FIX_0_390180644 FIX(0.390180644) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_175875602 FIX(1.175875602) -#define FIX_1_501321110 FIX(1.501321110) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_1_961570560 FIX(1.961570560) -#define FIX_2_053119869 FIX(2.053119869) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_072711026 FIX(3.072711026) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL(void) -jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - - tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; - tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; - - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_ISLOW_SUPPORTED */ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/Source/External/LibJPEG/jidctred.c b/Source/External/LibJPEG/jidctred.c index 911899b..421f3c7 100644 --- a/Source/External/LibJPEG/jidctred.c +++ b/Source/External/LibJPEG/jidctred.c @@ -1,398 +1,398 @@ -/* - * jidctred.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains inverse-DCT routines that produce reduced-size output: - * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. - * - * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) - * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step - * with an 8-to-4 step that produces the four averages of two adjacent outputs - * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). - * These steps were derived by computing the corresponding values at the end - * of the normal LL&M code, then simplifying as much as possible. - * - * 1x1 is trivial: just take the DC coefficient divided by 8. - * - * See jidctint.c for additional comments. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef IDCT_SCALING_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling is the same as in jidctint.c. */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ -#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ -#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ -#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ -#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ -#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ -#else -#define FIX_0_211164243 FIX(0.211164243) -#define FIX_0_509795579 FIX(0.509795579) -#define FIX_0_601344887 FIX(0.601344887) -#define FIX_0_720959822 FIX(0.720959822) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_850430095 FIX(0.850430095) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_061594337 FIX(1.061594337) -#define FIX_1_272758580 FIX(1.272758580) -#define FIX_1_451774981 FIX(1.451774981) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_172734803 FIX(2.172734803) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_624509785 FIX(3.624509785) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - */ - -GLOBAL(void) -jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process column 4, because second pass won't use it */ - if (ctr == DCTSIZE-4) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && - inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine term 4 for 4x4 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= (CONST_BITS+1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - - tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) - + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = (INT32) wsptr[7]; - z2 = (INT32) wsptr[5]; - z3 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[1]; - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - */ - -GLOBAL(void) -jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp10, z1; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process columns 2,4,6 */ - if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - - continue; - } - - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 = z1 << (CONST_BITS+2); - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); - } - - /* Pass 2: process 2 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - - /* Odd part */ - - tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ - + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ - + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ - + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - */ - -GLOBAL(void) -jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - int dcval; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS - - /* We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - dcval = (int) DESCALE((INT32) dcval, 3); - - output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; -} - -#endif /* IDCT_SCALING_SUPPORTED */ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (INT32) wsptr[7]; + z2 = (INT32) wsptr[5]; + z3 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/Source/External/LibJPEG/jinclude.h b/Source/External/LibJPEG/jinclude.h index cf7ef6f..bb64c03 100644 --- a/Source/External/LibJPEG/jinclude.h +++ b/Source/External/LibJPEG/jinclude.h @@ -1,92 +1,92 @@ -/* - * jinclude.h - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file exists to provide a single place to fix any problems with - * including the wrong system include files. (Common problems are taken - * care of by the standard jconfig symbols, but on really weird systems - * you may have to edit this file.) - * - * NOTE: this file is NOT intended to be included by applications using the - * JPEG library. Most applications need only include jpeglib.h. - */ - - -/* Include auto-config file to find out which system include files we need. */ - -#include "jconfig.h" /* auto configuration options */ -#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ - -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include . - * Otherwise, we get them from or ; we may have to - * pull in as well. - * Note that the core JPEG library does not require ; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without . - */ - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef NEED_SYS_TYPES_H -#include -#endif - -#include -#include - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in . - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in . - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - -#ifdef NEED_BSD_STRINGS - -#include -#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) -#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) - -#else /* not BSD, assume ANSI/SysV string lib */ - -#include -#define MEMZERO(target,size) xnOSMemSet((void *)(target), 0, (size_t)(size)) -#define MEMCOPY(dest,src,size) xnOSMemCopy((void *)(dest), (const void *)(src), (size_t)(size)) - -#endif - -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - -#define SIZEOF(object) ((size_t) sizeof(object)) - -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - */ - -#define JFREAD(file,buf,sizeofbuf) \ - ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) xnOSMemSet((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) xnOSMemCopy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/Source/External/LibJPEG/jmemmgr.c b/Source/External/LibJPEG/jmemmgr.c index 8a4f652..eb3d870 100644 --- a/Source/External/LibJPEG/jmemmgr.c +++ b/Source/External/LibJPEG/jmemmgr.c @@ -1,1119 +1,1119 @@ -/* - * jmemmgr.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the JPEG system-independent memory management - * routines. This code is usable across a wide variety of machines; most - * of the system dependencies have been isolated in a separate file. - * The major functions provided here are: - * * pool-based allocation and freeing of memory; - * * policy decisions about how to divide available memory among the - * virtual arrays; - * * control logic for swapping virtual arrays between main memory and - * backing storage. - * The separate system-dependent file provides the actual backing-storage - * access code, and it contains the policy decision about how much total - * main memory to use. - * This file is system-dependent in the sense that some of its functions - * are unnecessary in some systems. For example, if there is enough virtual - * memory so that backing storage will never be used, much of the virtual - * array control logic could be removed. (Of course, if you have that much - * memory then you shouldn't care about a little bit of unused code...) - */ - -#define JPEG_INTERNALS -#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef NO_GETENV -#ifndef HAVE_STDLIB_H /* should declare getenv() */ -extern char * getenv JPP((const char * name)); -#endif -#endif - - -/* - * Some important notes: - * The allocation routines provided here must never return NULL. - * They should exit to error_exit if unsuccessful. - * - * It's not a good idea to try to merge the sarray and barray routines, - * even though they are textually almost the same, because samples are - * usually stored as bytes while coefficients are shorts or ints. Thus, - * in machines where byte pointers have a different representation from - * word pointers, the resulting machine code could not be the same. - */ - - -/* - * Many machines require storage alignment: longs must start on 4-byte - * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() - * always returns pointers that are multiples of the worst-case alignment - * requirement, and we had better do so too. - * There isn't any really portable way to determine the worst-case alignment - * requirement. This module assumes that the alignment requirement is - * multiples of sizeof(ALIGN_TYPE). - * By default, we define ALIGN_TYPE as double. This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_TYPE smaller. - * The only place I know of where this will NOT work is certain Macintosh - * 680x0 compilers that define double as a 10-byte IEEE extended float. - * Doing 10-byte alignment is counterproductive because longwords won't be - * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have - * such a compiler. - */ - -#ifndef ALIGN_TYPE /* so can override from jconfig.h */ -#define ALIGN_TYPE double -#endif - - -/* - * We allocate objects from "pools", where each pool is gotten with a single - * request to jpeg_get_small() or jpeg_get_large(). There is no per-object - * overhead within a pool, except for alignment padding. Each pool has a - * header with a link to the next pool of the same class. - * Small and large pool headers are identical except that the latter's - * link pointer must be FAR on 80x86 machines. - * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE - * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple - * of the alignment requirement of ALIGN_TYPE. - */ - -typedef union small_pool_struct * small_pool_ptr; - -typedef union small_pool_struct { - struct { - small_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} small_pool_hdr; - -typedef union large_pool_struct FAR * large_pool_ptr; - -typedef union large_pool_struct { - struct { - large_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} large_pool_hdr; - - -/* - * Here is the full definition of a memory manager object. - */ - -typedef struct { - struct jpeg_memory_mgr pub; /* public fields */ - - /* Each pool identifier (lifetime class) names a linked list of pools. */ - small_pool_ptr small_list[JPOOL_NUMPOOLS]; - large_pool_ptr large_list[JPOOL_NUMPOOLS]; - - /* Since we only have one lifetime class of virtual arrays, only one - * linked list is necessary (for each datatype). Note that the virtual - * array control blocks being linked together are actually stored somewhere - * in the small-pool list. - */ - jvirt_sarray_ptr virt_sarray_list; - jvirt_barray_ptr virt_barray_list; - - /* This counts total space obtained from jpeg_get_small/large */ - long total_space_allocated; - - /* alloc_sarray and alloc_barray set this value for use by virtual - * array routines. - */ - JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ -} my_memory_mgr; - -typedef my_memory_mgr * my_mem_ptr; - - -/* - * The control blocks for virtual arrays. - * Note that these blocks are allocated in the "small" pool area. - * System-dependent info for the associated backing store (if any) is hidden - * inside the backing_store_info struct. - */ - -struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_sarray_ptr next; /* link to next virtual sarray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - -struct jvirt_barray_control { - JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_barray_ptr next; /* link to next virtual barray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - - -#ifdef MEM_STATS /* optional extra stuff for statistics */ - -LOCAL(void) -print_mem_stats (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - - /* Since this is only a debugging stub, we can cheat a little by using - * fprintf directly rather than going through the trace message code. - * This is helpful because message parm array can't handle longs. - */ - fprintf(stderr, "Freeing pool %d, total space = %ld\n", - pool_id, mem->total_space_allocated); - - for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; - lhdr_ptr = lhdr_ptr->hdr.next) { - fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); - } - - for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; - shdr_ptr = shdr_ptr->hdr.next) { - fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); - } -} - -#endif /* MEM_STATS */ - - -LOCAL(void) -out_of_memory (j_common_ptr cinfo, int which) -/* Report an out-of-memory error and stop execution */ -/* If we compiled MEM_STATS support, report alloc requests before dying */ -{ -#ifdef MEM_STATS - cinfo->err->trace_level = 2; /* force self_destruct to report stats */ -#endif - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); -} - - -/* - * Allocation of "small" objects. - * - * For these, we use pooled storage. When a new pool must be created, - * we try to get enough space for the current request plus a "slop" factor, - * where the slop will be the amount of leftover space in the new pool. - * The speed vs. space tradeoff is largely determined by the slop values. - * A different slop value is provided for each pool class (lifetime), - * and we also distinguish the first pool of a class from later ones. - * NOTE: the values given work fairly well on both 16- and 32-bit-int - * machines, but may be too small if longs are 64 bits or more. - */ - -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = -{ - 1600, /* first PERMANENT pool */ - 16000 /* first IMAGE pool */ -}; - -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = -{ - 0, /* additional PERMANENT pools */ - 5000 /* additional IMAGE pools */ -}; - -#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ - - -METHODDEF(void *) -alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "small" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr hdr_ptr, prev_hdr_ptr; - char * data_ptr; - size_t odd_bytes, min_request, slop; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) - out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* See if space is available in any existing pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - prev_hdr_ptr = NULL; - hdr_ptr = mem->small_list[pool_id]; - while (hdr_ptr != NULL) { - if (hdr_ptr->hdr.bytes_left >= sizeofobject) - break; /* found pool with enough space */ - prev_hdr_ptr = hdr_ptr; - hdr_ptr = hdr_ptr->hdr.next; - } - - /* Time to make a new pool? */ - if (hdr_ptr == NULL) { - /* min_request is what we need now, slop is what will be leftover */ - min_request = sizeofobject + SIZEOF(small_pool_hdr); - if (prev_hdr_ptr == NULL) /* first pool in class? */ - slop = first_pool_slop[pool_id]; - else - slop = extra_pool_slop[pool_id]; - /* Don't ask for more than MAX_ALLOC_CHUNK */ - if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) - slop = (size_t) (MAX_ALLOC_CHUNK-min_request); - /* Try to get space, if fail reduce slop and try again */ - for (;;) { - hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); - if (hdr_ptr != NULL) - break; - slop /= 2; - if (slop < MIN_SLOP) /* give up when it gets real small */ - out_of_memory(cinfo, 2); /* jpeg_get_small failed */ - } - mem->total_space_allocated += min_request + slop; - /* Success, initialize the new pool header and add to end of list */ - hdr_ptr->hdr.next = NULL; - hdr_ptr->hdr.bytes_used = 0; - hdr_ptr->hdr.bytes_left = sizeofobject + slop; - if (prev_hdr_ptr == NULL) /* first pool in class? */ - mem->small_list[pool_id] = hdr_ptr; - else - prev_hdr_ptr->hdr.next = hdr_ptr; - } - - /* OK, allocate the object from the current pool */ - data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ - data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ - hdr_ptr->hdr.bytes_used += sizeofobject; - hdr_ptr->hdr.bytes_left -= sizeofobject; - - return (void *) data_ptr; -} - - -/* - * Allocation of "large" objects. - * - * The external semantics of these are the same as "small" objects, - * except that FAR pointers are used on 80x86. However the pool - * management heuristics are quite different. We assume that each - * request is large enough that it may as well be passed directly to - * jpeg_get_large; the pool management just links everything together - * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. - */ - -METHODDEF(void FAR *) -alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "large" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - large_pool_ptr hdr_ptr; - size_t odd_bytes; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) - out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* Always make a new pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); - if (hdr_ptr == NULL) - out_of_memory(cinfo, 4); /* jpeg_get_large failed */ - mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); - - /* Success, initialize the new pool header and add to list */ - hdr_ptr->hdr.next = mem->large_list[pool_id]; - /* We maintain space counts in each pool header for statistical purposes, - * even though they are not needed for allocation. - */ - hdr_ptr->hdr.bytes_used = sizeofobject; - hdr_ptr->hdr.bytes_left = 0; - mem->large_list[pool_id] = hdr_ptr; - - return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ -} - - -/* - * Creation of 2-D sample arrays. - * The pointers are in near heap, the samples themselves in FAR heap. - * - * To minimize allocation overhead and to allow I/O of large contiguous - * blocks, we allocate the sample rows in groups of as many rows as possible - * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. - * NB: the virtual array control routines, later in this file, know about - * this chunking of rows. The rowsperchunk value is left in the mem manager - * object so that it can be saved away if this sarray is the workspace for - * a virtual array. - */ - -METHODDEF(JSAMPARRAY) -alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) -/* Allocate a 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JSAMPARRAY result; - JSAMPROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) samplesperrow * SIZEOF(JSAMPLE)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow - * SIZEOF(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; - } - } - - return result; -} - - -/* - * Creation of 2-D coefficient-block arrays. - * This is essentially the same as the code for sample arrays, above. - */ - -METHODDEF(JBLOCKARRAY) -alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) -/* Allocate a 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JBLOCKARRAY result; - JBLOCKROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) blocksperrow * SIZEOF(JBLOCK)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow - * SIZEOF(JBLOCK))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += blocksperrow; - } - } - - return result; -} - - -/* - * About virtual array management: - * - * The above "normal" array routines are only used to allocate strip buffers - * (as wide as the image, but just a few rows high). Full-image-sized buffers - * are handled as "virtual" arrays. The array is still accessed a strip at a - * time, but the memory manager must save the whole array for repeated - * accesses. The intended implementation is that there is a strip buffer in - * memory (as high as is possible given the desired memory limit), plus a - * backing file that holds the rest of the array. - * - * The request_virt_array routines are told the total size of the image and - * the maximum number of rows that will be accessed at once. The in-memory - * buffer must be at least as large as the maxaccess value. - * - * The request routines create control blocks but not the in-memory buffers. - * That is postponed until realize_virt_arrays is called. At that time the - * total amount of space needed is known (approximately, anyway), so free - * memory can be divided up fairly. - * - * The access_virt_array routines are responsible for making a specific strip - * area accessible (after reading or writing the backing file, if necessary). - * Note that the access routines are told whether the caller intends to modify - * the accessed strip; during a read-only pass this saves having to rewrite - * data to disk. The access routines are also responsible for pre-zeroing - * any newly accessed rows, if pre-zeroing was requested. - * - * In current usage, the access requests are usually for nonoverlapping - * strips; that is, successive access start_row numbers differ by exactly - * num_rows = maxaccess. This means we can get good performance with simple - * buffer dump/reload logic, by making the in-memory buffer be a multiple - * of the access height; then there will never be accesses across bufferload - * boundaries. The code will still work with overlapping access requests, - * but it doesn't handle bufferload overlaps very efficiently. - */ - - -METHODDEF(jvirt_sarray_ptr) -request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_sarray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_sarray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->samplesperrow = samplesperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ - mem->virt_sarray_list = result; - - return result; -} - - -METHODDEF(jvirt_barray_ptr) -request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_barray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_barray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->blocksperrow = blocksperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_barray_list; /* add to list of virtual arrays */ - mem->virt_barray_list = result; - - return result; -} - - -METHODDEF(void) -realize_virt_arrays (j_common_ptr cinfo) -/* Allocate the in-memory buffers for any unrealized virtual arrays */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - long space_per_minheight, maximum_space, avail_mem; - long minheights, max_minheights; - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - /* Compute the minimum space needed (maxaccess rows in each buffer) - * and the maximum space needed (full image height in each buffer). - * These may be of use to the system-dependent jpeg_mem_available routine. - */ - space_per_minheight = 0; - maximum_space = 0; - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - } - } - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - } - } - - if (space_per_minheight <= 0) - return; /* no unrealized arrays, no work */ - - /* Determine amount of memory to actually use; this is system-dependent. */ - avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, - mem->total_space_allocated); - - /* If the maximum space needed is available, make all the buffers full - * height; otherwise parcel it out with the same number of minheights - * in each buffer. - */ - if (avail_mem >= maximum_space) - max_minheights = 1000000000L; - else { - max_minheights = avail_mem / space_per_minheight; - /* If there doesn't seem to be enough space, try to get the minimum - * anyway. This allows a "stub" implementation of jpeg_mem_available(). - */ - if (max_minheights <= 0) - max_minheights = 1; - } - - /* Allocate the in-memory buffers and initialize backing store as needed. */ - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - sptr->rows_in_mem = sptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); - jpeg_open_backing_store(cinfo, & sptr->b_s_info, - (long) sptr->rows_in_array * - (long) sptr->samplesperrow * - (long) SIZEOF(JSAMPLE)); - sptr->b_s_open = TRUE; - } - sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); - sptr->rowsperchunk = mem->last_rowsperchunk; - sptr->cur_start_row = 0; - sptr->first_undef_row = 0; - sptr->dirty = FALSE; - } - } - - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - bptr->rows_in_mem = bptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); - jpeg_open_backing_store(cinfo, & bptr->b_s_info, - (long) bptr->rows_in_array * - (long) bptr->blocksperrow * - (long) SIZEOF(JBLOCK)); - bptr->b_s_open = TRUE; - } - bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); - bptr->rowsperchunk = mem->last_rowsperchunk; - bptr->cur_start_row = 0; - bptr->first_undef_row = 0; - bptr->dirty = FALSE; - } - } -} - - -LOCAL(void) -do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual sample array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -LOCAL(void) -do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual coefficient-block array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -METHODDEF(JSAMPARRAY) -access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual sample array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_sarray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_sarray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -METHODDEF(JBLOCKARRAY) -access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual block array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_barray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_barray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -/* - * Release all objects belonging to a specified pool. - */ - -METHODDEF(void) -free_pool (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - size_t space_freed; - - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - -#ifdef MEM_STATS - if (cinfo->err->trace_level > 1) - print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ -#endif - - /* If freeing IMAGE pool, close any virtual arrays first */ - if (pool_id == JPOOL_IMAGE) { - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->b_s_open) { /* there may be no backing store */ - sptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); - } - } - mem->virt_sarray_list = NULL; - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->b_s_open) { /* there may be no backing store */ - bptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); - } - } - mem->virt_barray_list = NULL; - } - - /* Release large objects */ - lhdr_ptr = mem->large_list[pool_id]; - mem->large_list[pool_id] = NULL; - - while (lhdr_ptr != NULL) { - large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; - space_freed = lhdr_ptr->hdr.bytes_used + - lhdr_ptr->hdr.bytes_left + - SIZEOF(large_pool_hdr); - jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - lhdr_ptr = next_lhdr_ptr; - } - - /* Release small objects */ - shdr_ptr = mem->small_list[pool_id]; - mem->small_list[pool_id] = NULL; - - while (shdr_ptr != NULL) { - small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; - space_freed = shdr_ptr->hdr.bytes_used + - shdr_ptr->hdr.bytes_left + - SIZEOF(small_pool_hdr); - jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - shdr_ptr = next_shdr_ptr; - } -} - - -/* - * Close up shop entirely. - * Note that this cannot be called unless cinfo->mem is non-NULL. - */ - -METHODDEF(void) -self_destruct (j_common_ptr cinfo) -{ - int pool; - - /* Close all backing store, release all memory. - * Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - free_pool(cinfo, pool); - } - - /* Release the memory manager control block too. */ - jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); - cinfo->mem = NULL; /* ensures I will be called only once */ - - jpeg_mem_term(cinfo); /* system-dependent cleanup */ -} - - -/* - * Memory manager initialization. - * When this is called, only the error manager pointer is valid in cinfo! - */ - -GLOBAL(void) -jinit_memory_mgr (j_common_ptr cinfo) -{ - my_mem_ptr mem; - long max_to_use; - int pool; - size_t test_mac; - - cinfo->mem = NULL; /* for safety if init fails */ - - /* Check for configuration errors. - * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably - * doesn't reflect any real hardware alignment requirement. - * The test is a little tricky: for X>0, X and X-1 have no one-bits - * in common if and only if X is a power of 2, ie has only one one-bit. - * Some compilers may give an "unreachable code" warning here; ignore it. - */ - if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) - ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); - /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be - * a multiple of SIZEOF(ALIGN_TYPE). - * Again, an "unreachable code" warning may be ignored here. - * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. - */ - test_mac = (size_t) MAX_ALLOC_CHUNK; - if ((long) test_mac != MAX_ALLOC_CHUNK || - (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) - ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); - - max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ - - /* Attempt to allocate memory manager's control block */ - mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); - - if (mem == NULL) { - jpeg_mem_term(cinfo); /* system-dependent cleanup */ - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); - } - - /* OK, fill in the method pointers */ - mem->pub.alloc_small = alloc_small; - mem->pub.alloc_large = alloc_large; - mem->pub.alloc_sarray = alloc_sarray; - mem->pub.alloc_barray = alloc_barray; - mem->pub.request_virt_sarray = request_virt_sarray; - mem->pub.request_virt_barray = request_virt_barray; - mem->pub.realize_virt_arrays = realize_virt_arrays; - mem->pub.access_virt_sarray = access_virt_sarray; - mem->pub.access_virt_barray = access_virt_barray; - mem->pub.free_pool = free_pool; - mem->pub.self_destruct = self_destruct; - - /* Make MAX_ALLOC_CHUNK accessible to other modules */ - mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; - - /* Initialize working state */ - mem->pub.max_memory_to_use = max_to_use; - - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - mem->small_list[pool] = NULL; - mem->large_list[pool] = NULL; - } - mem->virt_sarray_list = NULL; - mem->virt_barray_list = NULL; - - mem->total_space_allocated = SIZEOF(my_memory_mgr); - - /* Declare ourselves open for business */ - cinfo->mem = & mem->pub; - - /* Check for an environment variable JPEGMEM; if found, override the - * default max_memory setting from jpeg_mem_init. Note that the - * surrounding application may again override this value. - * If your system doesn't support getenv(), define NO_GETENV to disable - * this feature. - */ -/* -#ifndef NO_GETENV - { char * memenv; - - if ((memenv = getenv("JPEGMEM")) != NULL) { - char ch = 'x'; - - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { - if (ch == 'm' || ch == 'M') - max_to_use *= 1000L; - mem->pub.max_memory_to_use = max_to_use * 1000L; - } - } - } -#endif -*/ -} +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += min_request + slop; + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + long space_per_minheight, maximum_space, avail_mem; + long minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +/* +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif +*/ +} diff --git a/Source/External/LibJPEG/jmemnobs.c b/Source/External/LibJPEG/jmemnobs.c index 6aa1e92..eb8c337 100644 --- a/Source/External/LibJPEG/jmemnobs.c +++ b/Source/External/LibJPEG/jmemnobs.c @@ -1,109 +1,109 @@ -/* - * jmemnobs.c - * - * Copyright (C) 1992-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides a really simple implementation of the system- - * dependent portion of the JPEG memory manager. This implementation - * assumes that no backing-store files are needed: all required space - * can be obtained from malloc(). - * This is very portable in the sense that it'll compile on almost anything, - * but you'd better have lots of main memory (or virtual memory) if you want - * to process big images. - * Note that the max_memory_to_use option is ignored by this implementation. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ -extern void * malloc JPP((size_t size)); -extern void free JPP((void *ptr)); -#endif - - -/* - * Memory allocation and freeing are controlled by the regular library - * routines malloc() and free(). - */ - -GLOBAL(void *) -jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void *) malloc(sizeofobject); -} - -GLOBAL(void) -jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * "Large" objects are treated the same as "small" ones. - * NB: although we include FAR keywords in the routine declarations, - * this file won't actually work in 80x86 small/medium model; at least, - * you probably won't be able to process useful-size images in only 64KB. - */ - -GLOBAL(void FAR *) -jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void FAR *) malloc(sizeofobject); -} - -GLOBAL(void) -jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" - */ - -GLOBAL(long) -jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) -{ - return max_bytes_needed; -} - - -/* - * Backing store (temporary file) management. - * Since jpeg_mem_available always promised the moon, - * this should never be called and we can just error out. - */ - -GLOBAL(void) -jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) -{ - ERREXIT(cinfo, JERR_NO_BACKING_STORE); -} - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. Here, there isn't any. - */ - -GLOBAL(long) -jpeg_mem_init (j_common_ptr cinfo) -{ - return 0; /* just set max_memory_to_use to 0 */ -} - -GLOBAL(void) -jpeg_mem_term (j_common_ptr cinfo) -{ - /* no work */ -} +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/Source/External/LibJPEG/jmemsys.h b/Source/External/LibJPEG/jmemsys.h index 2a87961..6c3c6d3 100644 --- a/Source/External/LibJPEG/jmemsys.h +++ b/Source/External/LibJPEG/jmemsys.h @@ -1,198 +1,198 @@ -/* - * jmemsys.h - * - * Copyright (C) 1992-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file defines the interface between the system-independent - * and system-dependent portions of the JPEG memory manager. No other - * modules need include it. (The system-independent portion is jmemmgr.c; - * there are several different versions of the system-dependent portion.) - * - * This file works as-is for the system-dependent memory managers supplied - * in the IJG distribution. You may need to modify it if you write a - * custom memory manager. If system-dependent changes are needed in - * this file, the best method is to #ifdef them based on a configuration - * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR - * and USE_MAC_MEMMGR. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_get_small jGetSmall -#define jpeg_free_small jFreeSmall -#define jpeg_get_large jGetLarge -#define jpeg_free_large jFreeLarge -#define jpeg_mem_available jMemAvail -#define jpeg_open_backing_store jOpenBackStore -#define jpeg_mem_init jMemInit -#define jpeg_mem_term jMemTerm -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - -EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); -EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); - -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - -EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); -EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); - -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - -#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ -#define MAX_ALLOC_CHUNK 1000000000L -#endif - -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - -EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ - -#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ - - -#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ - -typedef unsigned short XMSH; /* type of extended-memory handles */ -typedef unsigned short EMSH; /* type of expanded-memory handles */ - -typedef union { - short file_handle; /* DOS file handle if it's a temp file */ - XMSH xms_handle; /* handle if it's a chunk of XMS */ - EMSH ems_handle; /* handle if it's a chunk of EMS */ -} handle_union; - -#endif /* USE_MSDOS_MEMMGR */ - -#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ -#include -#endif /* USE_MAC_MEMMGR */ - - -typedef struct backing_store_struct * backing_store_ptr; - -typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ - JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); - - /* Private fields for system-dependent backing-store management */ -#ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ - handle_union handle; /* reference to backing-store storage object */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else -#ifdef USE_MAC_MEMMGR - /* For the Mac manager (jmemmac.c), we need: */ - short temp_file; /* file reference number to temp file */ - FSSpec tempSpec; /* the FSSpec for the temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else - /* For a typical implementation with temp files, we need: */ - FILE * temp_file; /* stdio reference to temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -#endif -#endif -} backing_store_info; - - -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - -EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - -EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/Source/External/LibJPEG/jmorecfg.h b/Source/External/LibJPEG/jmorecfg.h index a840d6a..014732f 100644 --- a/Source/External/LibJPEG/jmorecfg.h +++ b/Source/External/LibJPEG/jmorecfg.h @@ -1,366 +1,366 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -//typedef long INT32; -typedef signed int INT32; -#endif - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ -#define METHODDEF(type) static type -/* a function used only in its module: */ -#define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type -/* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#undef FAR - -#ifdef NEED_FAR_POINTERS -#define FAR far -#else -#define FAR -#endif - - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -#ifndef HAVE_BOOLEAN -typedef int boolean; -#endif -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - -/* Capability options common to encoder and decoder: */ - -#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ -#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +//typedef long INT32; +typedef signed int INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#undef FAR + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/Source/External/LibJPEG/jpegint.h b/Source/External/LibJPEG/jpegint.h index 685a361..95b00d4 100644 --- a/Source/External/LibJPEG/jpegint.h +++ b/Source/External/LibJPEG/jpegint.h @@ -1,392 +1,392 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides common declarations for the various JPEG modules. - * These declarations are considered internal to the JPEG library; most - * applications using the library shouldn't need to include this file. - */ - - -/* Declarations for both compression & decompression */ - -typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ -} J_BUF_MODE; - -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ -#define CSTATE_START 100 /* after create_compress */ -#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ -#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ -#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ -#define DSTATE_START 200 /* after create_decompress */ -#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ -#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ -#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ -#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ -#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ -#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ -#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ -#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ -#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ -#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ - - -/* Declarations for compression modules */ - -/* Master control module */ -struct jpeg_comp_master { - JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); - JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean call_pass_startup; /* True if pass_startup must be called */ - boolean is_last_pass; /* True during last pass */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_c_main_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); -}; - -/* Compression preprocessing (downsampling input buffer control) */ -struct jpeg_c_prep_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_c_coef_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); -}; - -/* Colorspace conversion */ -struct jpeg_color_converter { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); -}; - -/* Downsampling */ -struct jpeg_downsampler { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Forward DCT (also controls coefficient quantization) */ -struct jpeg_forward_dct { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); -}; - -/* Entropy encoding */ -struct jpeg_entropy_encoder { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); - JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); -}; - -/* Marker writing */ -struct jpeg_marker_writer { - JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); - JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); - /* These routines are exported to allow insertion of extra markers */ - /* Probably only COM and APPn markers should be written this way */ - JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); - JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); -}; - - -/* Declarations for decompression modules */ - -/* Master control module */ -struct jpeg_decomp_master { - JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ -}; - -/* Input control module */ -struct jpeg_input_controller { - JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); - JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean has_multiple_scans; /* True if file has multiple scans */ - boolean eoi_reached; /* True when EOI has been consumed */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_d_main_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_d_coef_controller { - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); - JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; -}; - -/* Decompression postprocessing (color quantization buffer control) */ -struct jpeg_d_post_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Marker reading & parsing */ -struct jpeg_marker_reader { - JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ - jpeg_marker_parser_method read_restart_marker; - - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ - boolean saw_SOI; /* found SOI? */ - boolean saw_SOF; /* found SOF? */ - int next_restart_num; /* next restart number expected (0-7) */ - unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ -}; - -/* Entropy decoding */ -struct jpeg_entropy_decoder { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ - boolean insufficient_data; /* set TRUE after emitting warning */ -}; - -/* Inverse DCT (also performs dequantization) */ -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -struct jpeg_inverse_dct { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; -}; - -/* Upsampling (note that upsampler must also call color converter) */ -struct jpeg_upsampler { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Colorspace conversion */ -struct jpeg_color_deconverter { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); -}; - -/* Color quantization or color precision reduction */ -struct jpeg_color_quantizer { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); - JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); -}; - - -/* Miscellaneous useful macros */ - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_compress_master jICompress -#define jinit_c_master_control jICMaster -#define jinit_c_main_controller jICMainC -#define jinit_c_prep_controller jICPrepC -#define jinit_c_coef_controller jICCoefC -#define jinit_color_converter jICColor -#define jinit_downsampler jIDownsampler -#define jinit_forward_dct jIFDCT -#define jinit_huff_encoder jIHEncoder -#define jinit_phuff_encoder jIPHEncoder -#define jinit_marker_writer jIMWriter -#define jinit_master_decompress jIDMaster -#define jinit_d_main_controller jIDMainC -#define jinit_d_coef_controller jIDCoefC -#define jinit_d_post_controller jIDPostC -#define jinit_input_controller jIInCtlr -#define jinit_marker_reader jIMReader -#define jinit_huff_decoder jIHDecoder -#define jinit_phuff_decoder jIPHDecoder -#define jinit_inverse_dct jIIDCT -#define jinit_upsampler jIUpsampler -#define jinit_color_deconverter jIDColor -#define jinit_1pass_quantizer jI1Quant -#define jinit_2pass_quantizer jI2Quant -#define jinit_merged_upsampler jIMUpsampler -#define jinit_memory_mgr jIMemMgr -#define jdiv_round_up jDivRound -#define jround_up jRound -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jzero_far jZeroFar -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Compression module initialization routines */ -EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); -EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ -EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); - -/* Utility routines in jutils.c */ -EXTERN(long) jdiv_round_up JPP((long a, long b)); -EXTERN(long) jround_up JPP((long a, long b)); -EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); -EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -/* Constant tables in jutils.c */ -#if 0 /* This table is not actually needed in v6a */ -extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ -#endif -extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ - -/* Suppress undefined-structure complaints if necessary. */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -#endif -#endif /* INCOMPLETE_TYPES_BROKEN */ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/Source/External/LibJPEG/jpeglib.h b/Source/External/LibJPEG/jpeglib.h index 73dbbbb..a5c66b0 100644 --- a/Source/External/LibJPEG/jpeglib.h +++ b/Source/External/LibJPEG/jpeglib.h @@ -1,1105 +1,1105 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jconfig.h" /* widely used configuration options */ -#endif -#include "jmorecfg.h" /* seldom changed options */ - - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ - -#define JPEG_LIB_VERSION 62 /* Version 6b */ - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. - */ - int DCT_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ - boolean component_needed; /* do we need the value of this component? */ - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - -/* The decompressor can save APPn and COM markers in a list of these: */ - -typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; - -struct jpeg_marker_struct { - jpeg_saved_marker_ptr next; /* next in list, or NULL */ - UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ - unsigned int original_length; /* # bytes of data in the file */ - unsigned int data_length; /* # bytes of data saved at data[] */ - JOCTET FAR * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ -}; - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ -} J_COLOR_SPACE; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - void * client_data; /* Available for use by application */\ - boolean is_decompressor; /* So common code can tell which is which */\ - int global_state /* For checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - UINT8 JFIF_major_version; /* What to write for the JFIF version number */ - UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; - jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ - int script_space_size; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ - UINT8 JFIF_major_version; /* JFIF version number */ - UINT8 JFIF_minor_version; - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ - jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; - - /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_CreateCompress jCreaCompress -#define jpeg_CreateDecompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_m_header jWrtMHeader -#define jpeg_write_m_byte jWrtMByte -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_save_markers jSaveMarkers -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); - -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ -#define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) -#define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) -EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); -EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); -/* Destruction of JPEG compression objects */ -EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); -EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); - -/* Default parameter setup for compression */ -EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.doc concerning safe usage. */ -EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ -EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); -EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Control saving of COM and APPn markers into marker_list. */ -EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#ifdef __cplusplus -} -#endif - - -#endif /* JPEGLIB_H */ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +} +#endif + + +#endif /* JPEGLIB_H */ diff --git a/Source/External/LibJPEG/jquant1.c b/Source/External/LibJPEG/jquant1.c index aaa34a1..b2f96aa 100644 --- a/Source/External/LibJPEG/jquant1.c +++ b/Source/External/LibJPEG/jquant1.c @@ -1,856 +1,856 @@ -/* - * jquant1.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains 1-pass color quantization (color mapping) routines. - * These routines provide mapping to a fixed color map using equally spaced - * color values. Optional Floyd-Steinberg or ordered dithering is available. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef QUANT_1PASS_SUPPORTED - - -/* - * The main purpose of 1-pass quantization is to provide a fast, if not very - * high quality, colormapped output capability. A 2-pass quantizer usually - * gives better visual quality; however, for quantized grayscale output this - * quantizer is perfectly adequate. Dithering is highly recommended with this - * quantizer, though you can turn it off if you really want to. - * - * In 1-pass quantization the colormap must be chosen in advance of seeing the - * image. We use a map consisting of all combinations of Ncolors[i] color - * values for the i'th component. The Ncolors[] values are chosen so that - * their product, the total number of colors, is no more than that requested. - * (In most cases, the product will be somewhat less.) - * - * Since the colormap is orthogonal, the representative value for each color - * component can be determined without considering the other components; - * then these indexes can be combined into a colormap index by a standard - * N-dimensional-array-subscript calculation. Most of the arithmetic involved - * can be precalculated and stored in the lookup table colorindex[]. - * colorindex[i][j] maps pixel value j in component i to the nearest - * representative value (grid plane) for that component; this index is - * multiplied by the array stride for component i, so that the - * index of the colormap entry closest to a given pixel value is just - * sum( colorindex[component-number][pixel-component-value] ) - * Aside from being fast, this scheme allows for variable spacing between - * representative values with no additional lookup cost. - * - * If gamma correction has been applied in color conversion, it might be wise - * to adjust the color grid spacing so that the representative colors are - * equidistant in linear space. At this writing, gamma correction is not - * implemented by jdcolor, so nothing is done here. - */ - - -/* Declarations for ordered dithering. - * - * We use a standard 16x16 ordered dither array. The basic concept of ordered - * dithering is described in many references, for instance Dale Schumacher's - * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). - * In place of Schumacher's comparisons against a "threshold" value, we add a - * "dither" value to the input pixel and then round the result to the nearest - * output value. The dither value is equivalent to (0.5 - threshold) times - * the distance between output values. For ordered dithering, we assume that - * the output colors are equally spaced; if not, results will probably be - * worse, since the dither may be too much or too little at a given point. - * - * The normal calculation would be to form pixel value + dither, range-limit - * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. - * We can skip the separate range-limiting step by extending the colorindex - * table in both directions. - */ - -#define ODITHER_SIZE 16 /* dimension of dither matrix */ -/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ -#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ -#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ - -typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; -typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; - -static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { - /* Bayer's order-4 dither array. Generated by the code given in - * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. - * The values in this array must range from 0 to ODITHER_CELLS-1. - */ - { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, - { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, - { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, - { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, - { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, - { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, - { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, - { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, - { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, - { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, - { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, - { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, - { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, - { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, - { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, - { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } -}; - - -/* Declarations for Floyd-Steinberg dithering. - * - * Errors are accumulated into the array fserrors[], at a resolution of - * 1/16th of a pixel count. The error at a given pixel is propagated - * to its not-yet-processed neighbors using the standard F-S fractions, - * ... (here) 7/16 - * 3/16 5/16 1/16 - * We work left-to-right on even rows, right-to-left on odd rows. - * - * We can get away with a single array (holding one row's worth of errors) - * by using it to store the current row's errors at pixel columns not yet - * processed, but the next row's errors at columns already processed. We - * need only a few extra variables to hold the errors immediately around the - * current column. (If we are lucky, those variables are in registers, but - * even if not, they're probably cheaper to access than array elements are.) - * - * The fserrors[] array is indexed [component#][position]. - * We provide (#columns + 2) entries per component; the extra entry at each - * end saves us from special-casing the first and last pixels. - * - * Note: on a wide image, we might not have enough room in a PC's near data - * segment to hold the error array; so it is allocated with alloc_large. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef INT16 FSERROR; /* 16 bits should be enough */ -typedef int LOCFSERROR; /* use 'int' for calculation temps */ -#else -typedef INT32 FSERROR; /* may need more than 16 bits */ -typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ -#endif - -typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ - - -/* Private subobject */ - -#define MAX_Q_COMPS 4 /* max components I can handle */ - -typedef struct { - struct jpeg_color_quantizer pub; /* public fields */ - - /* Initially allocated colormap is saved here */ - JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ - int sv_actual; /* number of entries in use */ - - JSAMPARRAY colorindex; /* Precomputed mapping for speed */ - /* colorindex[i][j] = index of color closest to pixel value j in component i, - * premultiplied as described above. Since colormap indexes must fit into - * JSAMPLEs, the entries of this array will too. - */ - boolean is_padded; /* is the colorindex padded for odither? */ - - int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ - - /* Variables for ordered dithering */ - int row_index; /* cur row's vertical index in dither matrix */ - ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ - - /* Variables for Floyd-Steinberg dithering */ - FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ - boolean on_odd_row; /* flag to remember which row we are on */ -} my_cquantizer; - -typedef my_cquantizer * my_cquantize_ptr; - - -/* - * Policy-making subroutines for create_colormap and create_colorindex. - * These routines determine the colormap to be used. The rest of the module - * only assumes that the colormap is orthogonal. - * - * * select_ncolors decides how to divvy up the available colors - * among the components. - * * output_value defines the set of representative values for a component. - * * largest_input_value defines the mapping from input values to - * representative values for a component. - * Note that the latter two routines may impose different policies for - * different components, though this is not currently done. - */ - - -LOCAL(int) -select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) -/* Determine allocation of desired colors to components, */ -/* and fill in Ncolors[] array to indicate choice. */ -/* Return value is total number of colors (product of Ncolors[] values). */ -{ - int nc = cinfo->out_color_components; /* number of color components */ - int max_colors = cinfo->desired_number_of_colors; - int total_colors, iroot, i, j; - boolean changed; - long temp; - static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; - - /* We can allocate at least the nc'th root of max_colors per component. */ - /* Compute floor(nc'th root of max_colors). */ - iroot = 1; - do { - iroot++; - temp = iroot; /* set temp = iroot ** nc */ - for (i = 1; i < nc; i++) - temp *= iroot; - } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ - iroot--; /* now iroot = floor(root) */ - - /* Must have at least 2 color values per component */ - if (iroot < 2) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); - - /* Initialize to iroot color values for each component */ - total_colors = 1; - for (i = 0; i < nc; i++) { - Ncolors[i] = iroot; - total_colors *= iroot; - } - /* We may be able to increment the count for one or more components without - * exceeding max_colors, though we know not all can be incremented. - * Sometimes, the first component can be incremented more than once! - * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) - * In RGB colorspace, try to increment G first, then R, then B. - */ - do { - changed = FALSE; - for (i = 0; i < nc; i++) { - j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); - /* calculate new total_colors if Ncolors[j] is incremented */ - temp = total_colors / Ncolors[j]; - temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ - if (temp > (long) max_colors) - break; /* won't fit, done with this pass */ - Ncolors[j]++; /* OK, apply the increment */ - total_colors = (int) temp; - changed = TRUE; - } - } while (changed); - - return total_colors; -} - - -LOCAL(int) -output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return j'th output value, where j will range from 0 to maxj */ -/* The output values must fall in 0..MAXJSAMPLE in increasing order */ -{ - /* We always provide values 0 and MAXJSAMPLE for each component; - * any additional values are equally spaced between these limits. - * (Forcing the upper and lower values to the limits ensures that - * dithering can't produce a color outside the selected gamut.) - */ - return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); -} - - -LOCAL(int) -largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return largest input value that should map to j'th output value */ -/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ -{ - /* Breakpoints are halfway between values returned by output_value */ - return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); -} - - -/* - * Create the colormap. - */ - -LOCAL(void) -create_colormap (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPARRAY colormap; /* Created colormap */ - int total_colors; /* Number of distinct output colors */ - int i,j,k, nci, blksize, blkdist, ptr, val; - - /* Select number of colors for each component */ - total_colors = select_ncolors(cinfo, cquantize->Ncolors); - - /* Report selected color counts */ - if (cinfo->out_color_components == 3) - TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, - total_colors, cquantize->Ncolors[0], - cquantize->Ncolors[1], cquantize->Ncolors[2]); - else - TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); - - /* Allocate and fill in the colormap. */ - /* The colors are ordered in the map in standard row-major order, */ - /* i.e. rightmost (highest-indexed) color changes most rapidly. */ - - colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); - - /* blksize is number of adjacent repeated entries for a component */ - /* blkdist is distance between groups of identical entries for a component */ - blkdist = total_colors; - - for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colormap entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blkdist / nci; - for (j = 0; j < nci; j++) { - /* Compute j'th output value (out of nci) for component */ - val = output_value(cinfo, i, j, nci-1); - /* Fill in all colormap entries that have this value of this component */ - for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { - /* fill in blksize entries beginning at ptr */ - for (k = 0; k < blksize; k++) - colormap[i][ptr+k] = (JSAMPLE) val; - } - } - blkdist = blksize; /* blksize of this color is blkdist of next */ - } - - /* Save the colormap in private storage, - * where it will survive color quantization mode changes. - */ - cquantize->sv_colormap = colormap; - cquantize->sv_actual = total_colors; -} - - -/* - * Create the color index table. - */ - -LOCAL(void) -create_colorindex (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPROW indexptr; - int i,j,k, nci, blksize, val, pad; - - /* For ordered dither, we pad the color index tables by MAXJSAMPLE in - * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). - * This is not necessary in the other dithering modes. However, we - * flag whether it was done in case user changes dithering mode. - */ - if (cinfo->dither_mode == JDITHER_ORDERED) { - pad = MAXJSAMPLE*2; - cquantize->is_padded = TRUE; - } else { - pad = 0; - cquantize->is_padded = FALSE; - } - - cquantize->colorindex = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (MAXJSAMPLE+1 + pad), - (JDIMENSION) cinfo->out_color_components); - - /* blksize is number of adjacent repeated entries for a component */ - blksize = cquantize->sv_actual; - - for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colorindex entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blksize / nci; - - /* adjust colorindex pointers to provide padding at negative indexes. */ - if (pad) - cquantize->colorindex[i] += MAXJSAMPLE; - - /* in loop, val = index of current output value, */ - /* and k = largest j that maps to current val */ - indexptr = cquantize->colorindex[i]; - val = 0; - k = largest_input_value(cinfo, i, 0, nci-1); - for (j = 0; j <= MAXJSAMPLE; j++) { - while (j > k) /* advance val if past boundary */ - k = largest_input_value(cinfo, i, ++val, nci-1); - /* premultiply so that no multiplication needed in main processing */ - indexptr[j] = (JSAMPLE) (val * blksize); - } - /* Pad at both ends if necessary */ - if (pad) - for (j = 1; j <= MAXJSAMPLE; j++) { - indexptr[-j] = indexptr[0]; - indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; - } - } -} - - -/* - * Create an ordered-dither array for a component having ncolors - * distinct output values. - */ - -LOCAL(ODITHER_MATRIX_PTR) -make_odither_array (j_decompress_ptr cinfo, int ncolors) -{ - ODITHER_MATRIX_PTR odither; - int j,k; - INT32 num,den; - - odither = (ODITHER_MATRIX_PTR) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(ODITHER_MATRIX)); - /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). - * Hence the dither value for the matrix cell with fill order f - * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). - * On 16-bit-int machine, be careful to avoid overflow. - */ - den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); - for (j = 0; j < ODITHER_SIZE; j++) { - for (k = 0; k < ODITHER_SIZE; k++) { - num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) - * MAXJSAMPLE; - /* Ensure round towards zero despite C's lack of consistency - * about rounding negative values in integer division... - */ - odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); - } - } - return odither; -} - - -/* - * Create the ordered-dither tables. - * Components having the same number of representative colors may - * share a dither table. - */ - -LOCAL(void) -create_odither_tables (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - ODITHER_MATRIX_PTR odither; - int i, j, nci; - - for (i = 0; i < cinfo->out_color_components; i++) { - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - odither = NULL; /* search for matching prior component */ - for (j = 0; j < i; j++) { - if (nci == cquantize->Ncolors[j]) { - odither = cquantize->odither[j]; - break; - } - } - if (odither == NULL) /* need a new table? */ - odither = make_odither_array(cinfo, nci); - cquantize->odither[i] = odither; - } -} - - -/* - * Map some rows of pixels to the output colormapped representation. - */ - -METHODDEF(void) -color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPARRAY colorindex = cquantize->colorindex; - register int pixcode, ci; - register JSAMPROW ptrin, ptrout; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - register int nc = cinfo->out_color_components; - - for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = 0; - for (ci = 0; ci < nc; ci++) { - pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); - } - *ptrout++ = (JSAMPLE) pixcode; - } - } -} - - -METHODDEF(void) -color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register int pixcode; - register JSAMPROW ptrin, ptrout; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); - *ptrout++ = (JSAMPLE) pixcode; - } - } -} - - -METHODDEF(void) -quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with ordered dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - int * dither; /* points to active row of dither matrix */ - int row_index, col_index; /* current indexes into dither matrix */ - int nc = cinfo->out_color_components; - int ci; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - row_index = cquantize->row_index; - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - colorindex_ci = cquantize->colorindex[ci]; - dither = cquantize->odither[ci][row_index]; - col_index = 0; - - for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, - * select output value, accumulate into output code for this pixel. - * Range-limiting need not be done explicitly, as we have extended - * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the - * required amount of padding. - */ - *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; - input_ptr += nc; - output_ptr++; - col_index = (col_index + 1) & ODITHER_MASK; - } - } - /* Advance row index for next row */ - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; - } -} - - -METHODDEF(void) -quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, with ordered dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register int pixcode; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; - int * dither0; /* points to active row of dither matrix */ - int * dither1; - int * dither2; - int row_index, col_index; /* current indexes into dither matrix */ - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - row_index = cquantize->row_index; - input_ptr = input_buf[row]; - output_ptr = output_buf[row]; - dither0 = cquantize->odither[0][row_index]; - dither1 = cquantize->odither[1][row_index]; - dither2 = cquantize->odither[2][row_index]; - col_index = 0; - - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + - dither0[col_index]]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + - dither1[col_index]]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + - dither2[col_index]]); - *output_ptr++ = (JSAMPLE) pixcode; - col_index = (col_index + 1) & ODITHER_MASK; - } - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; - } -} - - -METHODDEF(void) -quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with Floyd-Steinberg dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register LOCFSERROR cur; /* current error or pixel value */ - LOCFSERROR belowerr; /* error for pixel below cur */ - LOCFSERROR bpreverr; /* error for below/prev col */ - LOCFSERROR bnexterr; /* error for below/next col */ - LOCFSERROR delta; - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - JSAMPROW colormap_ci; - int pixcode; - int nc = cinfo->out_color_components; - int dir; /* 1 for left-to-right, -1 for right-to-left */ - int dirnc; /* dir * nc */ - int ci; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; - SHIFT_TEMPS - - for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - input_ptr += (width-1) * nc; /* so point to rightmost pixel */ - output_ptr += width-1; - dir = -1; - dirnc = -nc; - errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ - } else { - /* work left to right in this row */ - dir = 1; - dirnc = nc; - errorptr = cquantize->fserrors[ci]; /* => entry before first column */ - } - colorindex_ci = cquantize->colorindex[ci]; - colormap_ci = cquantize->sv_colormap[ci]; - /* Preset error values: no error propagated to first pixel from left */ - cur = 0; - /* and no error propagated to row below yet */ - belowerr = bpreverr = 0; - - for (col = width; col > 0; col--) { - /* cur holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size - * of the range_limit array. - */ - cur += GETJSAMPLE(*input_ptr); - cur = GETJSAMPLE(range_limit[cur]); - /* Select output value, accumulate into output code for this pixel */ - pixcode = GETJSAMPLE(colorindex_ci[cur]); - *output_ptr += (JSAMPLE) pixcode; - /* Compute actual representation error at this pixel */ - /* Note: we can do this even though we don't have the final */ - /* pixel code, because the colormap is orthogonal. */ - cur -= GETJSAMPLE(colormap_ci[pixcode]); - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - bnexterr = cur; - delta = cur * 2; - cur += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr + cur); - cur += delta; /* form error * 5 */ - bpreverr = belowerr + cur; - belowerr = bnexterr; - cur += delta; /* form error * 7 */ - /* At this point cur contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - input_ptr += dirnc; /* advance input ptr to next column */ - output_ptr += dir; /* advance output ptr to next column */ - errorptr += dir; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error value into the - * final fserrors[] entry. Note we need not unload belowerr because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ - } - cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); - } -} - - -/* - * Allocate workspace for Floyd-Steinberg errors. - */ - -LOCAL(void) -alloc_fs_workspace (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - size_t arraysize; - int i; - - arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); - for (i = 0; i < cinfo->out_color_components; i++) { - cquantize->fserrors[i] = (FSERRPTR) - (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - } -} - - -/* - * Initialize for one-pass color quantization. - */ - -METHODDEF(void) -start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - size_t arraysize; - int i; - - /* Install my colormap. */ - cinfo->colormap = cquantize->sv_colormap; - cinfo->actual_number_of_colors = cquantize->sv_actual; - - /* Initialize for desired dithering mode. */ - switch (cinfo->dither_mode) { - case JDITHER_NONE: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = color_quantize3; - else - cquantize->pub.color_quantize = color_quantize; - break; - case JDITHER_ORDERED: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = quantize3_ord_dither; - else - cquantize->pub.color_quantize = quantize_ord_dither; - cquantize->row_index = 0; /* initialize state for ordered dither */ - /* If user changed to ordered dither from another mode, - * we must recreate the color index table with padding. - * This will cost extra space, but probably isn't very likely. - */ - if (! cquantize->is_padded) - create_colorindex(cinfo); - /* Create ordered-dither tables if we didn't already. */ - if (cquantize->odither[0] == NULL) - create_odither_tables(cinfo); - break; - case JDITHER_FS: - cquantize->pub.color_quantize = quantize_fs_dither; - cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ - /* Allocate Floyd-Steinberg workspace if didn't already. */ - if (cquantize->fserrors[0] == NULL) - alloc_fs_workspace(cinfo); - /* Initialize the propagated errors to zero. */ - arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); - for (i = 0; i < cinfo->out_color_components; i++) - jzero_far((void FAR *) cquantize->fserrors[i], arraysize); - break; - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } -} - - -/* - * Finish up at the end of the pass. - */ - -METHODDEF(void) -finish_pass_1_quant (j_decompress_ptr cinfo) -{ - /* no work in 1-pass case */ -} - - -/* - * Switch to a new external colormap between output passes. - * Shouldn't get to this module! - */ - -METHODDEF(void) -new_color_map_1_quant (j_decompress_ptr cinfo) -{ - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - - -/* - * Module initialization routine for 1-pass color quantization. - */ - -GLOBAL(void) -jinit_1pass_quantizer (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize; - - cquantize = (my_cquantize_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; - cquantize->pub.start_pass = start_pass_1_quant; - cquantize->pub.finish_pass = finish_pass_1_quant; - cquantize->pub.new_color_map = new_color_map_1_quant; - cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ - cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ - - /* Make sure my internal arrays won't overflow */ - if (cinfo->out_color_components > MAX_Q_COMPS) - ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); - - /* Create the colormap and color index table. */ - create_colormap(cinfo); - create_colorindex(cinfo); - - /* Allocate Floyd-Steinberg workspace now if requested. - * We do this now since it is FAR storage and may affect the memory - * manager's space calculations. If the user changes to FS dither - * mode in a later pass, we will allocate the space then, and will - * possibly overrun the max_memory_to_use setting. - */ - if (cinfo->dither_mode == JDITHER_FS) - alloc_fs_workspace(cinfo); -} - -#endif /* QUANT_1PASS_SUPPORTED */ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/Source/External/LibJPEG/jquant2.c b/Source/External/LibJPEG/jquant2.c index 87a3920..af601e3 100644 --- a/Source/External/LibJPEG/jquant2.c +++ b/Source/External/LibJPEG/jquant2.c @@ -1,1310 +1,1310 @@ -/* - * jquant2.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains 2-pass color quantization (color mapping) routines. - * These routines provide selection of a custom color map for an image, - * followed by mapping of the image to that color map, with optional - * Floyd-Steinberg dithering. - * It is also possible to use just the second pass to map to an arbitrary - * externally-given color map. - * - * Note: ordered dithering is not supported, since there isn't any fast - * way to compute intercolor distances; it's unclear that ordered dither's - * fundamental assumptions even hold with an irregularly spaced color map. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef QUANT_2PASS_SUPPORTED - - -/* - * This module implements the well-known Heckbert paradigm for color - * quantization. Most of the ideas used here can be traced back to - * Heckbert's seminal paper - * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", - * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. - * - * In the first pass over the image, we accumulate a histogram showing the - * usage count of each possible color. To keep the histogram to a reasonable - * size, we reduce the precision of the input; typical practice is to retain - * 5 or 6 bits per color, so that 8 or 4 different input values are counted - * in the same histogram cell. - * - * Next, the color-selection step begins with a box representing the whole - * color space, and repeatedly splits the "largest" remaining box until we - * have as many boxes as desired colors. Then the mean color in each - * remaining box becomes one of the possible output colors. - * - * The second pass over the image maps each input pixel to the closest output - * color (optionally after applying a Floyd-Steinberg dithering correction). - * This mapping is logically trivial, but making it go fast enough requires - * considerable care. - * - * Heckbert-style quantizers vary a good deal in their policies for choosing - * the "largest" box and deciding where to cut it. The particular policies - * used here have proved out well in experimental comparisons, but better ones - * may yet be found. - * - * In earlier versions of the IJG code, this module quantized in YCbCr color - * space, processing the raw upsampled data without a color conversion step. - * This allowed the color conversion math to be done only once per colormap - * entry, not once per pixel. However, that optimization precluded other - * useful optimizations (such as merging color conversion with upsampling) - * and it also interfered with desired capabilities such as quantizing to an - * externally-supplied colormap. We have therefore abandoned that approach. - * The present code works in the post-conversion color space, typically RGB. - * - * To improve the visual quality of the results, we actually work in scaled - * RGB space, giving G distances more weight than R, and R in turn more than - * B. To do everything in integer math, we must use integer scale factors. - * The 2/3/1 scale factors used here correspond loosely to the relative - * weights of the colors in the NTSC grayscale equation. - * If you want to use this code to quantize a non-RGB color space, you'll - * probably need to change these scale factors. - */ - -#define R_SCALE 2 /* scale R distances by this much */ -#define G_SCALE 3 /* scale G distances by this much */ -#define B_SCALE 1 /* and B by this much */ - -/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined - * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B - * and B,G,R orders. If you define some other weird order in jmorecfg.h, - * you'll get compile errors until you extend this logic. In that case - * you'll probably want to tweak the histogram sizes too. - */ - -#if RGB_RED == 0 -#define C0_SCALE R_SCALE -#endif -#if RGB_BLUE == 0 -#define C0_SCALE B_SCALE -#endif -#if RGB_GREEN == 1 -#define C1_SCALE G_SCALE -#endif -#if RGB_RED == 2 -#define C2_SCALE R_SCALE -#endif -#if RGB_BLUE == 2 -#define C2_SCALE B_SCALE -#endif - - -/* - * First we have the histogram data structure and routines for creating it. - * - * The number of bits of precision can be adjusted by changing these symbols. - * We recommend keeping 6 bits for G and 5 each for R and B. - * If you have plenty of memory and cycles, 6 bits all around gives marginally - * better results; if you are short of memory, 5 bits all around will save - * some space but degrade the results. - * To maintain a fully accurate histogram, we'd need to allocate a "long" - * (preferably unsigned long) for each cell. In practice this is overkill; - * we can get by with 16 bits per cell. Few of the cell counts will overflow, - * and clamping those that do overflow to the maximum value will give close- - * enough results. This reduces the recommended histogram size from 256Kb - * to 128Kb, which is a useful savings on PC-class machines. - * (In the second pass the histogram space is re-used for pixel mapping data; - * in that capacity, each cell must be able to store zero to the number of - * desired colors. 16 bits/cell is plenty for that too.) - * Since the JPEG code is intended to run in small memory model on 80x86 - * machines, we can't just allocate the histogram in one chunk. Instead - * of a true 3-D array, we use a row of pointers to 2-D arrays. Each - * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and - * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that - * on 80x86 machines, the pointer row is in near memory but the actual - * arrays are in far memory (same arrangement as we use for image arrays). - */ - -#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ - -/* These will do the right thing for either R,G,B or B,G,R color order, - * but you may not like the results for other color orders. - */ -#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ -#define HIST_C1_BITS 6 /* bits of precision in G histogram */ -#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ - -/* Number of elements along histogram axes. */ -#define HIST_C0_ELEMS (1<cquantize; - register JSAMPROW ptr; - register histptr histp; - register hist3d histogram = cquantize->histogram; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - ptr = input_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the histogram */ - histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] - [GETJSAMPLE(ptr[1]) >> C1_SHIFT] - [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; - /* increment, check for overflow and undo increment if so. */ - if (++(*histp) <= 0) - (*histp)--; - ptr += 3; - } - } -} - - -/* - * Next we have the really interesting routines: selection of a colormap - * given the completed histogram. - * These routines work with a list of "boxes", each representing a rectangular - * subset of the input color space (to histogram precision). - */ - -typedef struct { - /* The bounds of the box (inclusive); expressed as histogram indexes */ - int c0min, c0max; - int c1min, c1max; - int c2min, c2max; - /* The volume (actually 2-norm) of the box */ - INT32 volume; - /* The number of nonzero histogram cells within this box */ - long colorcount; -} box; - -typedef box * boxptr; - - -LOCAL(boxptr) -find_biggest_color_pop (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest color population */ -/* Returns NULL if no splittable boxes remain */ -{ - register boxptr boxp; - register int i; - register long maxc = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->colorcount > maxc && boxp->volume > 0) { - which = boxp; - maxc = boxp->colorcount; - } - } - return which; -} - - -LOCAL(boxptr) -find_biggest_volume (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest (scaled) volume */ -/* Returns NULL if no splittable boxes remain */ -{ - register boxptr boxp; - register int i; - register INT32 maxv = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->volume > maxv) { - which = boxp; - maxv = boxp->volume; - } - } - return which; -} - - -LOCAL(void) -update_box (j_decompress_ptr cinfo, boxptr boxp) -/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ -/* and recompute its volume and population */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - histptr histp; - int c0,c1,c2; - int c0min,c0max,c1min,c1max,c2min,c2max; - INT32 dist0,dist1,dist2; - long ccount; - - c0min = boxp->c0min; c0max = boxp->c0max; - c1min = boxp->c1min; c1max = boxp->c1max; - c2min = boxp->c2min; c2max = boxp->c2max; - - if (c0max > c0min) - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; - } - } - have_c0min: - if (c0max > c0min) - for (c0 = c0max; c0 >= c0min; c0--) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; - } - } - have_c0max: - if (c1max > c1min) - for (c1 = c1min; c1 <= c1max; c1++) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; - } - } - have_c1min: - if (c1max > c1min) - for (c1 = c1max; c1 >= c1min; c1--) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; - } - } - have_c1max: - if (c2max > c2min) - for (c2 = c2min; c2 <= c2max; c2++) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; - } - } - have_c2min: - if (c2max > c2min) - for (c2 = c2max; c2 >= c2min; c2--) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; - } - } - have_c2max: - - /* Update box volume. - * We use 2-norm rather than real volume here; this biases the method - * against making long narrow boxes, and it has the side benefit that - * a box is splittable iff norm > 0. - * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; - * after which, we scale according to the selected distance scale factors. - */ - dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; - dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; - dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; - boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - - /* Now scan remaining volume of box and compute population */ - ccount = 0; - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++, histp++) - if (*histp != 0) { - ccount++; - } - } - boxp->colorcount = ccount; -} - - -LOCAL(int) -median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, - int desired_colors) -/* Repeatedly select and split the largest box until we have enough boxes */ -{ - int n,lb; - int c0,c1,c2,cmax; - register boxptr b1,b2; - - while (numboxes < desired_colors) { - /* Select box to split. - * Current algorithm: by population for first half, then by volume. - */ - if (numboxes*2 <= desired_colors) { - b1 = find_biggest_color_pop(boxlist, numboxes); - } else { - b1 = find_biggest_volume(boxlist, numboxes); - } - if (b1 == NULL) /* no splittable boxes left! */ - break; - b2 = &boxlist[numboxes]; /* where new box will go */ - /* Copy the color bounds to the new box. */ - b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; - b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; - /* Choose which axis to split the box on. - * Current algorithm: longest scaled axis. - * See notes in update_box about scaling distances. - */ - c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; - c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; - c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; - /* We want to break any ties in favor of green, then red, blue last. - * This code does the right thing for R,G,B or B,G,R color orders only. - */ -#if RGB_RED == 0 - cmax = c1; n = 1; - if (c0 > cmax) { cmax = c0; n = 0; } - if (c2 > cmax) { n = 2; } -#else - cmax = c1; n = 1; - if (c2 > cmax) { cmax = c2; n = 2; } - if (c0 > cmax) { n = 0; } -#endif - /* Choose split point along selected axis, and update box bounds. - * Current algorithm: split at halfway point. - * (Since the box has been shrunk to minimum volume, - * any split will produce two nonempty subboxes.) - * Note that lb value is max for lower box, so must be < old max. - */ - switch (n) { - case 0: - lb = (b1->c0max + b1->c0min) / 2; - b1->c0max = lb; - b2->c0min = lb+1; - break; - case 1: - lb = (b1->c1max + b1->c1min) / 2; - b1->c1max = lb; - b2->c1min = lb+1; - break; - case 2: - lb = (b1->c2max + b1->c2min) / 2; - b1->c2max = lb; - b2->c2min = lb+1; - break; - } - /* Update stats for boxes */ - update_box(cinfo, b1); - update_box(cinfo, b2); - numboxes++; - } - return numboxes; -} - - -LOCAL(void) -compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) -/* Compute representative color for a box, put it in colormap[icolor] */ -{ - /* Current algorithm: mean weighted by pixels (not colors) */ - /* Note it is important to get the rounding correct! */ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - histptr histp; - int c0,c1,c2; - int c0min,c0max,c1min,c1max,c2min,c2max; - long count; - long total = 0; - long c0total = 0; - long c1total = 0; - long c2total = 0; - - c0min = boxp->c0min; c0max = boxp->c0max; - c1min = boxp->c1min; c1max = boxp->c1max; - c2min = boxp->c2min; c2max = boxp->c2max; - - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if ((count = *histp++) != 0) { - total += count; - c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; - } - } - } - - cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); - cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); - cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); -} - - -LOCAL(void) -select_colors (j_decompress_ptr cinfo, int desired_colors) -/* Master routine for color selection */ -{ - boxptr boxlist; - int numboxes; - int i; - - /* Allocate workspace for box list */ - boxlist = (boxptr) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); - /* Initialize one box containing whole space */ - numboxes = 1; - boxlist[0].c0min = 0; - boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; - boxlist[0].c1min = 0; - boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; - boxlist[0].c2min = 0; - boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; - /* Shrink it to actually-used volume and set its statistics */ - update_box(cinfo, & boxlist[0]); - /* Perform median-cut to produce final box list */ - numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); - /* Compute the representative color for each box, fill colormap */ - for (i = 0; i < numboxes; i++) - compute_color(cinfo, & boxlist[i], i); - cinfo->actual_number_of_colors = numboxes; - TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); -} - - -/* - * These routines are concerned with the time-critical task of mapping input - * colors to the nearest color in the selected colormap. - * - * We re-use the histogram space as an "inverse color map", essentially a - * cache for the results of nearest-color searches. All colors within a - * histogram cell will be mapped to the same colormap entry, namely the one - * closest to the cell's center. This may not be quite the closest entry to - * the actual input color, but it's almost as good. A zero in the cache - * indicates we haven't found the nearest color for that cell yet; the array - * is cleared to zeroes before starting the mapping pass. When we find the - * nearest color for a cell, its colormap index plus one is recorded in the - * cache for future use. The pass2 scanning routines call fill_inverse_cmap - * when they need to use an unfilled entry in the cache. - * - * Our method of efficiently finding nearest colors is based on the "locally - * sorted search" idea described by Heckbert and on the incremental distance - * calculation described by Spencer W. Thomas in chapter III.1 of Graphics - * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that - * the distances from a given colormap entry to each cell of the histogram can - * be computed quickly using an incremental method: the differences between - * distances to adjacent cells themselves differ by a constant. This allows a - * fairly fast implementation of the "brute force" approach of computing the - * distance from every colormap entry to every histogram cell. Unfortunately, - * it needs a work array to hold the best-distance-so-far for each histogram - * cell (because the inner loop has to be over cells, not colormap entries). - * The work array elements have to be INT32s, so the work array would need - * 256Kb at our recommended precision. This is not feasible in DOS machines. - * - * To get around these problems, we apply Thomas' method to compute the - * nearest colors for only the cells within a small subbox of the histogram. - * The work array need be only as big as the subbox, so the memory usage - * problem is solved. Furthermore, we need not fill subboxes that are never - * referenced in pass2; many images use only part of the color gamut, so a - * fair amount of work is saved. An additional advantage of this - * approach is that we can apply Heckbert's locality criterion to quickly - * eliminate colormap entries that are far away from the subbox; typically - * three-fourths of the colormap entries are rejected by Heckbert's criterion, - * and we need not compute their distances to individual cells in the subbox. - * The speed of this approach is heavily influenced by the subbox size: too - * small means too much overhead, too big loses because Heckbert's criterion - * can't eliminate as many colormap entries. Empirically the best subbox - * size seems to be about 1/512th of the histogram (1/8th in each direction). - * - * Thomas' article also describes a refined method which is asymptotically - * faster than the brute-force method, but it is also far more complex and - * cannot efficiently be applied to small subboxes. It is therefore not - * useful for programs intended to be portable to DOS machines. On machines - * with plenty of memory, filling the whole histogram in one shot with Thomas' - * refined method might be faster than the present code --- but then again, - * it might not be any faster, and it's certainly more complicated. - */ - - -/* log2(histogram cells in update box) for each axis; this can be adjusted */ -#define BOX_C0_LOG (HIST_C0_BITS-3) -#define BOX_C1_LOG (HIST_C1_BITS-3) -#define BOX_C2_LOG (HIST_C2_BITS-3) - -#define BOX_C0_ELEMS (1<actual_number_of_colors; - int maxc0, maxc1, maxc2; - int centerc0, centerc1, centerc2; - int i, x, ncolors; - INT32 minmaxdist, min_dist, max_dist, tdist; - INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ - - /* Compute true coordinates of update box's upper corner and center. - * Actually we compute the coordinates of the center of the upper-corner - * histogram cell, which are the upper bounds of the volume we care about. - * Note that since ">>" rounds down, the "center" values may be closer to - * min than to max; hence comparisons to them must be "<=", not "<". - */ - maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); - centerc0 = (minc0 + maxc0) >> 1; - maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); - centerc1 = (minc1 + maxc1) >> 1; - maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); - centerc2 = (minc2 + maxc2) >> 1; - - /* For each color in colormap, find: - * 1. its minimum squared-distance to any point in the update box - * (zero if color is within update box); - * 2. its maximum squared-distance to any point in the update box. - * Both of these can be found by considering only the corners of the box. - * We save the minimum distance for each color in mindist[]; - * only the smallest maximum distance is of interest. - */ - minmaxdist = 0x7FFFFFFFL; - - for (i = 0; i < numcolors; i++) { - /* We compute the squared-c0-distance term, then add in the other two. */ - x = GETJSAMPLE(cinfo->colormap[0][i]); - if (x < minc0) { - tdist = (x - minc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; - } else if (x > maxc0) { - tdist = (x - maxc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - min_dist = 0; - if (x <= centerc0) { - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; - } else { - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; - } - } - - x = GETJSAMPLE(cinfo->colormap[1][i]); - if (x < minc1) { - tdist = (x - minc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc1) { - tdist = (x - maxc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc1) { - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; - } else { - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; - } - } - - x = GETJSAMPLE(cinfo->colormap[2][i]); - if (x < minc2) { - tdist = (x - minc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc2) { - tdist = (x - maxc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc2) { - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; - } else { - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; - } - } - - mindist[i] = min_dist; /* save away the results */ - if (max_dist < minmaxdist) - minmaxdist = max_dist; - } - - /* Now we know that no cell in the update box is more than minmaxdist - * away from some colormap entry. Therefore, only colors that are - * within minmaxdist of some part of the box need be considered. - */ - ncolors = 0; - for (i = 0; i < numcolors; i++) { - if (mindist[i] <= minmaxdist) - colorlist[ncolors++] = (JSAMPLE) i; - } - return ncolors; -} - - -LOCAL(void) -find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) -/* Find the closest colormap entry for each cell in the update box, - * given the list of candidate colors prepared by find_nearby_colors. - * Return the indexes of the closest entries in the bestcolor[] array. - * This routine uses Thomas' incremental distance calculation method to - * find the distance from a colormap entry to successive cells in the box. - */ -{ - int ic0, ic1, ic2; - int i, icolor; - register INT32 * bptr; /* pointer into bestdist[] array */ - JSAMPLE * cptr; /* pointer into bestcolor[] array */ - INT32 dist0, dist1; /* initial distance values */ - register INT32 dist2; /* current distance in inner loop */ - INT32 xx0, xx1; /* distance increments */ - register INT32 xx2; - INT32 inc0, inc1, inc2; /* initial values for increments */ - /* This array holds the distance to the nearest-so-far color for each cell */ - INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Initialize best-distance for each cell of the update box */ - bptr = bestdist; - for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) - *bptr++ = 0x7FFFFFFFL; - - /* For each color selected by find_nearby_colors, - * compute its distance to the center of each cell in the box. - * If that's less than best-so-far, update best distance and color number. - */ - - /* Nominal steps between cell centers ("x" in Thomas article) */ -#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) -#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) -#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - - for (i = 0; i < numcolors; i++) { - icolor = GETJSAMPLE(colorlist[i]); - /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; - dist0 = inc0*inc0; - inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; - dist0 += inc1*inc1; - inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; - dist0 += inc2*inc2; - /* Form the initial difference increments */ - inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; - inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; - inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; - /* Now loop over all cells in box, updating distance per Thomas method */ - bptr = bestdist; - cptr = bestcolor; - xx0 = inc0; - for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { - dist1 = dist0; - xx1 = inc1; - for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { - dist2 = dist1; - xx2 = inc2; - for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { - if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; - } - dist2 += xx2; - xx2 += 2 * STEP_C2 * STEP_C2; - bptr++; - cptr++; - } - dist1 += xx1; - xx1 += 2 * STEP_C1 * STEP_C1; - } - dist0 += xx0; - xx0 += 2 * STEP_C0 * STEP_C0; - } - } -} - - -LOCAL(void) -fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) -/* Fill the inverse-colormap entries in the update box that contains */ -/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ -/* we can fill as many others as we wish.) */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - int minc0, minc1, minc2; /* lower left corner of update box */ - int ic0, ic1, ic2; - register JSAMPLE * cptr; /* pointer into bestcolor[] array */ - register histptr cachep; /* pointer into main cache array */ - /* This array lists the candidate colormap indexes. */ - JSAMPLE colorlist[MAXNUMCOLORS]; - int numcolors; /* number of candidate colors */ - /* This array holds the actually closest colormap index for each cell. */ - JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Convert cell coordinates to update box ID */ - c0 >>= BOX_C0_LOG; - c1 >>= BOX_C1_LOG; - c2 >>= BOX_C2_LOG; - - /* Compute true coordinates of update box's origin corner. - * Actually we compute the coordinates of the center of the corner - * histogram cell, which are the lower bounds of the volume we care about. - */ - minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); - minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); - minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - - /* Determine which colormap entries are close enough to be candidates - * for the nearest entry to some cell in the update box. - */ - numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); - - /* Determine the actually nearest colors. */ - find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, - bestcolor); - - /* Save the best color numbers (plus 1) in the main cache array */ - c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ - c1 <<= BOX_C1_LOG; - c2 <<= BOX_C2_LOG; - cptr = bestcolor; - for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { - for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { - cachep = & histogram[c0+ic0][c1+ic1][c2]; - for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { - *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); - } - } - } -} - - -/* - * Map some rows of pixels to the output colormapped representation. - */ - -METHODDEF(void) -pass2_no_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - register JSAMPROW inptr, outptr; - register histptr cachep; - register int c0, c1, c2; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the cache */ - c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; - c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; - c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; - cachep = & histogram[c0][c1][c2]; - /* If we have not seen this color before, find nearest colormap entry */ - /* and update the cache */ - if (*cachep == 0) - fill_inverse_cmap(cinfo, c0,c1,c2); - /* Now emit the colormap index for this cell */ - *outptr++ = (JSAMPLE) (*cachep - 1); - } - } -} - - -METHODDEF(void) -pass2_fs_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs Floyd-Steinberg dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ - LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ - LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - JSAMPROW inptr; /* => current input pixel */ - JSAMPROW outptr; /* => current output pixel */ - histptr cachep; - int dir; /* +1 or -1 depending on direction */ - int dir3; /* 3*dir, for advancing inptr & errorptr */ - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; - int *error_limit = cquantize->error_limiter; - JSAMPROW colormap0 = cinfo->colormap[0]; - JSAMPROW colormap1 = cinfo->colormap[1]; - JSAMPROW colormap2 = cinfo->colormap[2]; - SHIFT_TEMPS - - for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - inptr += (width-1) * 3; /* so point to rightmost pixel */ - outptr += width-1; - dir = -1; - dir3 = -3; - errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ - cquantize->on_odd_row = FALSE; /* flip for next time */ - } else { - /* work left to right in this row */ - dir = 1; - dir3 = 3; - errorptr = cquantize->fserrors; /* => entry before first real column */ - cquantize->on_odd_row = TRUE; /* flip for next time */ - } - /* Preset error values: no error propagated to first pixel from left */ - cur0 = cur1 = cur2 = 0; - /* and no error propagated to row below yet */ - belowerr0 = belowerr1 = belowerr2 = 0; - bpreverr0 = bpreverr1 = bpreverr2 = 0; - - for (col = width; col > 0; col--) { - /* curN holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); - cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); - cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); - /* Limit the error using transfer function set by init_error_limit. - * See comments with init_error_limit for rationale. - */ - cur0 = error_limit[cur0]; - cur1 = error_limit[cur1]; - cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); - * this sets the required size of the range_limit array. - */ - cur0 += GETJSAMPLE(inptr[0]); - cur1 += GETJSAMPLE(inptr[1]); - cur2 += GETJSAMPLE(inptr[2]); - cur0 = GETJSAMPLE(range_limit[cur0]); - cur1 = GETJSAMPLE(range_limit[cur1]); - cur2 = GETJSAMPLE(range_limit[cur2]); - /* Index into the cache with adjusted pixel value */ - cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; - /* If we have not seen this color before, find nearest colormap */ - /* entry and update the cache */ - if (*cachep == 0) - fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); - /* Now emit the colormap index for this cell */ - { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ - cur0 -= GETJSAMPLE(colormap0[pixcode]); - cur1 -= GETJSAMPLE(colormap1[pixcode]); - cur2 -= GETJSAMPLE(colormap2[pixcode]); - } - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - { register LOCFSERROR bnexterr, delta; - - bnexterr = cur0; /* Process component 0 */ - delta = cur0 * 2; - cur0 += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr0 + cur0); - cur0 += delta; /* form error * 5 */ - bpreverr0 = belowerr0 + cur0; - belowerr0 = bnexterr; - cur0 += delta; /* form error * 7 */ - bnexterr = cur1; /* Process component 1 */ - delta = cur1 * 2; - cur1 += delta; /* form error * 3 */ - errorptr[1] = (FSERROR) (bpreverr1 + cur1); - cur1 += delta; /* form error * 5 */ - bpreverr1 = belowerr1 + cur1; - belowerr1 = bnexterr; - cur1 += delta; /* form error * 7 */ - bnexterr = cur2; /* Process component 2 */ - delta = cur2 * 2; - cur2 += delta; /* form error * 3 */ - errorptr[2] = (FSERROR) (bpreverr2 + cur2); - cur2 += delta; /* form error * 5 */ - bpreverr2 = belowerr2 + cur2; - belowerr2 = bnexterr; - cur2 += delta; /* form error * 7 */ - } - /* At this point curN contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - inptr += dir3; /* Advance pixel pointers to next column */ - outptr += dir; - errorptr += dir3; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error values into the - * final fserrors[] entry. Note we need not unload belowerrN because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ - errorptr[1] = (FSERROR) bpreverr1; - errorptr[2] = (FSERROR) bpreverr2; - } -} - - -/* - * Initialize the error-limiting transfer function (lookup table). - * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be - * much less, otherwise obviously wrong pixels will be created. (Typical - * effects include weird fringes at color-area boundaries, isolated bright - * pixels in a dark area, etc.) The standard advice for avoiding this problem - * is to ensure that the "corners" of the color cube are allocated as output - * colors; then repeated errors in the same direction cannot cause cascading - * error buildup. However, that only prevents the error from getting - * completely out of hand; Aaron Giles reports that error limiting improves - * the results even with corner colors allocated. - * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty - * well, but the smoother transfer function used below is even better. Thanks - * to Aaron Giles for this idea. - */ - -LOCAL(void) -init_error_limit (j_decompress_ptr cinfo) -/* Allocate and fill in the error_limiter table */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - int * table; - int in, out; - - table = (int *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ - cquantize->error_limiter = table; - -#define STEPSIZE ((MAXJSAMPLE+1)/16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ - out = 0; - for (in = 0; in < STEPSIZE; in++, out++) { - table[in] = out; table[-in] = -out; - } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ - for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { - table[in] = out; table[-in] = -out; - } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ - for (; in <= MAXJSAMPLE; in++) { - table[in] = out; table[-in] = -out; - } -#undef STEPSIZE -} - - -/* - * Finish up at the end of each pass. - */ - -METHODDEF(void) -finish_pass1 (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - - /* Select the representative colors and fill in cinfo->colormap */ - cinfo->colormap = cquantize->sv_colormap; - select_colors(cinfo, cquantize->desired); - /* Force next pass to zero the color index table */ - cquantize->needs_zeroed = TRUE; -} - - -METHODDEF(void) -finish_pass2 (j_decompress_ptr cinfo) -{ - /* no work */ -} - - -/* - * Initialize for each processing pass. - */ - -METHODDEF(void) -start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - int i; - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; - - if (is_pre_scan) { - /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; - cquantize->pub.finish_pass = finish_pass1; - cquantize->needs_zeroed = TRUE; /* Always zero histogram */ - } else { - /* Set up method pointers */ - if (cinfo->dither_mode == JDITHER_FS) - cquantize->pub.color_quantize = pass2_fs_dither; - else - cquantize->pub.color_quantize = pass2_no_dither; - cquantize->pub.finish_pass = finish_pass2; - - /* Make sure color count is acceptable */ - i = cinfo->actual_number_of_colors; - if (i < 1) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); - if (i > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - - if (cinfo->dither_mode == JDITHER_FS) { - size_t arraysize = (size_t) ((cinfo->output_width + 2) * - (3 * SIZEOF(FSERROR))); - /* Allocate Floyd-Steinberg workspace if we didn't already. */ - if (cquantize->fserrors == NULL) - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - /* Initialize the propagated errors to zero. */ - jzero_far((void FAR *) cquantize->fserrors, arraysize); - /* Make the error-limit table if we didn't already. */ - if (cquantize->error_limiter == NULL) - init_error_limit(cinfo); - cquantize->on_odd_row = FALSE; - } - - } - /* Zero the histogram or inverse color map, if necessary */ - if (cquantize->needs_zeroed) { - for (i = 0; i < HIST_C0_ELEMS; i++) { - jzero_far((void FAR *) histogram[i], - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); - } - cquantize->needs_zeroed = FALSE; - } -} - - -/* - * Switch to a new external colormap between output passes. - */ - -METHODDEF(void) -new_color_map_2_quant (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - - /* Reset the inverse color map */ - cquantize->needs_zeroed = TRUE; -} - - -/* - * Module initialization routine for 2-pass color quantization. - */ - -GLOBAL(void) -jinit_2pass_quantizer (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize; - int i; - - cquantize = (my_cquantize_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; - cquantize->pub.start_pass = start_pass_2_quant; - cquantize->pub.new_color_map = new_color_map_2_quant; - cquantize->fserrors = NULL; /* flag optional arrays not allocated */ - cquantize->error_limiter = NULL; - - /* Make sure jdmaster didn't give me a case I can't handle */ - if (cinfo->out_color_components != 3) - ERREXIT(cinfo, JERR_NOTIMPL); - - /* Allocate the histogram/inverse colormap storage */ - cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); - for (i = 0; i < HIST_C0_ELEMS; i++) { - cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); - } - cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ - - /* Allocate storage for the completed colormap, if required. - * We do this now since it is FAR storage and may affect - * the memory manager's space calculations. - */ - if (cinfo->enable_2pass_quant) { - /* Make sure color count is acceptable */ - int desired = cinfo->desired_number_of_colors; - /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ - if (desired < 8) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (desired > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); - cquantize->desired = desired; - } else - cquantize->sv_colormap = NULL; - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; - - /* Allocate Floyd-Steinberg workspace if necessary. - * This isn't really needed until pass 2, but again it is FAR storage. - * Although we will cope with a later change in dither_mode, - * we do not promise to honor max_memory_to_use if dither_mode changes. - */ - if (cinfo->dither_mode == JDITHER_FS) { - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); - /* Might as well create the error-limiting table too. */ - init_error_limit(cinfo); - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/Source/External/LibJPEG/jutils.c b/Source/External/LibJPEG/jutils.c index 286cda2..d18a955 100644 --- a/Source/External/LibJPEG/jutils.c +++ b/Source/External/LibJPEG/jutils.c @@ -1,179 +1,179 @@ -/* - * jutils.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains tables and miscellaneous utility routines needed - * for both compression and decompression. - * Note we prefix all global names with "j" to minimize conflicts with - * a surrounding application. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element - * of a DCT block read in natural order (left to right, top to bottom). - */ - -#if 0 /* This table is not actually needed in v6a */ - -const int jpeg_zigzag_order[DCTSIZE2] = { - 0, 1, 5, 6, 14, 15, 27, 28, - 2, 4, 7, 13, 16, 26, 29, 42, - 3, 8, 12, 17, 25, 30, 41, 43, - 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, - 20, 22, 33, 38, 46, 51, 55, 60, - 21, 34, 37, 47, 50, 56, 59, 61, - 35, 36, 48, 49, 57, 58, 62, 63 -}; - -#endif - -/* - * jpeg_natural_order[i] is the natural-order position of the i'th element - * of zigzag order. - * - * When reading corrupted data, the Huffman decoders could attempt - * to reference an entry beyond the end of this array (if the decoded - * zero run length reaches past the end of the block). To prevent - * wild stores without adding an inner-loop test, we put some extra - * "63"s after the real entries. This will cause the extra coefficient - * to be stored in location 63 of the block, not somewhere random. - * The worst case would be a run-length of 15, which means we need 16 - * fake entries. - */ - -const int jpeg_natural_order[DCTSIZE2+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - - -/* - * Arithmetic utilities - */ - -GLOBAL(long) -jdiv_round_up (long a, long b) -/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ -/* Assumes a >= 0, b > 0 */ -{ - return (a + b - 1L) / b; -} - - -GLOBAL(long) -jround_up (long a, long b) -/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ -/* Assumes a >= 0, b > 0 */ -{ - a += b - 1L; - return a - (a % b); -} - - -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines below do it the hard way. (The performance cost - * is not all that great, because these routines aren't very heavily used.) - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ -#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) -#define FMEMZERO(target,size) MEMZERO(target,size) -#else /* 80x86 case, define if we can */ -#ifdef USE_FMEM -#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) -#endif -#endif - - -GLOBAL(void) -jcopy_sample_rows (JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols) -/* Copy some rows of samples from one place to another. - * num_rows rows are copied from input_array[source_row++] - * to output_array[dest_row++]; these areas may overlap for duplication. - * The source and destination arrays must be at least as wide as num_cols. - */ -{ - register JSAMPROW inptr, outptr; -#ifdef FMEMCOPY - register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); -#else - register JDIMENSION count; -#endif - register int row; - - input_array += source_row; - output_array += dest_row; - - for (row = num_rows; row > 0; row--) { - inptr = *input_array++; - outptr = *output_array++; -#ifdef FMEMCOPY - FMEMCOPY(outptr, inptr, count); -#else - for (count = num_cols; count > 0; count--) - *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ -#endif - } -} - - -GLOBAL(void) -jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks) -/* Copy a row of coefficient blocks from one place to another. */ -{ -#ifdef FMEMCOPY - FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); -#else - register JCOEFPTR inptr, outptr; - register long count; - - inptr = (JCOEFPTR) input_row; - outptr = (JCOEFPTR) output_row; - for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { - *outptr++ = *inptr++; - } -#endif -} - - -GLOBAL(void) -jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ -{ -#ifdef FMEMZERO - FMEMZERO(target, bytestozero); -#else - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -#endif -} +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/Source/External/LibJPEG/jversion.h b/Source/External/LibJPEG/jversion.h index dadd453..6472c58 100644 --- a/Source/External/LibJPEG/jversion.h +++ b/Source/External/LibJPEG/jversion.h @@ -1,14 +1,14 @@ -/* - * jversion.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains software version identification. - */ - - -#define JVERSION "6b 27-Mar-1998" - -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/Source/Utils/XnSensorServer/CMakeLists.txt b/Source/Utils/XnSensorServer/CMakeLists.txt new file mode 100644 index 0000000..7af0bf1 --- /dev/null +++ b/Source/Utils/XnSensorServer/CMakeLists.txt @@ -0,0 +1,43 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR} + ${XNCORE_INCLUDE_DIR} + ../../ +) + +# Get sources +# ------------ +file(GLOB ${XNSENSORSERVER_TARGET_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_executable( + ${XNSENSORSERVER_TARGET_NAME} + ${${XNSENSORSERVER_TARGET_NAME}_sources} +) + +target_link_libraries( + ${XNSENSORSERVER_TARGET_NAME} + ${XNSENSORSERVER_LIB_NAME} + ${XNDDK_LIB_NAME} + ${XNFORMAT_LIB_NAME} + ${XNDEVICESENSOR_LIB_NAME} + ${XNCORE_LIB_NAME} + ${OPENNI_LIB_NAME} + ${LIBJPEG_LIB_NAME} +) + +set_target_properties( + ${XNSENSORSERVER_TARGET_NAME} + PROPERTIES + INSTALL_RPATH "." +) + +# Set install dir +# --------------- +install( + TARGETS ${XNSENSORSERVER_TARGET_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) + diff --git a/Source/Utils/XnSensorServer/SensorServer.cpp b/Source/Utils/XnSensorServer/SensorServer.cpp index d81e64d..57aa0ea 100644 --- a/Source/Utils/XnSensorServer/SensorServer.cpp +++ b/Source/Utils/XnSensorServer/SensorServer.cpp @@ -1,80 +1,80 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_CHECK_RC(rc, what) \ - if (rc != XN_STATUS_OK) \ - { \ - printf("Failed to " what ": %s\n", xnGetStatusString(rc)); \ - return (rc); \ - } - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -int main(int argc, char* argv[]) -{ - XnStatus nRetVal = XN_STATUS_OK; - - printf("Starting sensor server...\n"); - - const XnChar* strConfigDir = "."; - if (argc >= 2) - { - strConfigDir = argv[1]; - } - - XnChar strConfigFile[XN_FILE_MAX_PATH]; - nRetVal = XnSensorServerGetGlobalConfigFile(strConfigDir, strConfigFile, XN_FILE_MAX_PATH); - XN_CHECK_RC(nRetVal, "Resolving global config file"); - - nRetVal = XnFormatsInitFromINIFile(strConfigFile); - XN_CHECK_RC(nRetVal, "Initializing DDK"); - -#if (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM) - xnLogSetOutputFolder("/var/log/primesense/XnSensorServer/"); -#endif - - printf("Running...\n"); - nRetVal = XnSensorServerRun(strConfigFile); - XN_CHECK_RC(nRetVal, "starting sensor server"); - - printf("\nShutting down sensor server...\n"); - XnDDKShutdown(); - - return 0; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_CHECK_RC(rc, what) \ + if (rc != XN_STATUS_OK) \ + { \ + printf("Failed to " what ": %s\n", xnGetStatusString(rc)); \ + return (rc); \ + } + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + XnStatus nRetVal = XN_STATUS_OK; + + printf("Starting sensor server...\n"); + + const XnChar* strConfigDir = "."; + if (argc >= 2) + { + strConfigDir = argv[1]; + } + + XnChar strConfigFile[XN_FILE_MAX_PATH]; + nRetVal = XnSensorServerGetGlobalConfigFile(strConfigDir, strConfigFile, XN_FILE_MAX_PATH); + XN_CHECK_RC(nRetVal, "Resolving global config file"); + + nRetVal = XnFormatsInitFromINIFile(strConfigFile); + XN_CHECK_RC(nRetVal, "Initializing DDK"); + +#if (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM || XN_PLATFORM == XN_PLATFORM_MACOSX) + xnLogSetOutputFolder("/var/log/primesense/XnSensorServer/"); +#endif + + printf("Running...\n"); + nRetVal = XnSensorServerRun(strConfigFile); + XN_CHECK_RC(nRetVal, "starting sensor server"); + + printf("\nShutting down sensor server...\n"); + XnDDKShutdown(); + + return 0; +} diff --git a/Source/XnCommon/XnCommon.h b/Source/XnCommon/XnCommon.h index ef5b9ee..042ac52 100644 --- a/Source/XnCommon/XnCommon.h +++ b/Source/XnCommon/XnCommon.h @@ -1,62 +1,62 @@ -/***************************************************************************** -* * -* PrimeSense Common * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Common is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Common is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Common. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_COMMON_H__ -#define __XN_COMMON_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_VENDOR_PRIMESENSE "PrimeSense" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef enum XnPrimeSenseErrorModules -{ - XN_ERROR_GROUP_SECURITY = 0, - XN_ERROR_GROUP_FORMATS = 1000, - XN_ERROR_GROUP_DDK = 2000, - XN_ERROR_GROUP_DEVICE = 3000, - XN_ERROR_GROUP_IO = 4000, - XN_ERROR_GROUP_EE_CORE = 5000, - XN_ERROR_GROUP_EE_FRAMEWORK = 6000, - XN_ERROR_GROUP_EE_NITE = 7000, -} XnPrimeSenseErrorModules; - -#define XN_PS_STATUS_MESSAGE_MAP_START(module) \ - XN_STATUS_MESSAGE_MAP_START_FROM(XN_ERROR_GROUP_PRIMESENSE, module) - -#define XN_PS_STATUS_MESSAGE_MAP_END(module) \ - XN_STATUS_MESSAGE_MAP_END_FROM(XN_ERROR_GROUP_PRIMESENSE, module) - +/***************************************************************************** +* * +* PrimeSense Common * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Common is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Common is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Common. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_COMMON_H__ +#define __XN_COMMON_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_VENDOR_PRIMESENSE "PrimeSense" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef enum XnPrimeSenseErrorModules +{ + XN_ERROR_GROUP_SECURITY = 0, + XN_ERROR_GROUP_FORMATS = 1000, + XN_ERROR_GROUP_DDK = 2000, + XN_ERROR_GROUP_DEVICE = 3000, + XN_ERROR_GROUP_IO = 4000, + XN_ERROR_GROUP_EE_CORE = 5000, + XN_ERROR_GROUP_EE_FRAMEWORK = 6000, + XN_ERROR_GROUP_EE_NITE = 7000, +} XnPrimeSenseErrorModules; + +#define XN_PS_STATUS_MESSAGE_MAP_START(module) \ + XN_STATUS_MESSAGE_MAP_START_FROM(XN_ERROR_GROUP_PRIMESENSE, module) + +#define XN_PS_STATUS_MESSAGE_MAP_END(module) \ + XN_STATUS_MESSAGE_MAP_END_FROM(XN_ERROR_GROUP_PRIMESENSE, module) + #endif // __XN_COMMON_H__ \ No newline at end of file diff --git a/Source/XnCore/CMakeLists.txt b/Source/XnCore/CMakeLists.txt new file mode 100644 index 0000000..c9520e9 --- /dev/null +++ b/Source/XnCore/CMakeLists.txt @@ -0,0 +1,35 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR}) +include_directories(${XNCORE_INCLUDE_DIR}) +include_directories(../) + +# Get sources +# ------------ +file(GLOB ${XNCORE_LIB_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_library( + ${XNCORE_LIB_NAME} + SHARED + ${${XNCORE_LIB_NAME}_sources} +) + +# Set link libraries +# ------------------- +target_link_libraries(${XNCORE_LIB_NAME} ${OPENNI_LIB_NAME}) +if(SENSOR_PLATFORM_MAC) + set_target_properties(${XNCORE_LIB_NAME} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR ${INSTALL_NAME_VALUE} + ) +endif() + +# Set install dir +# --------------- +install( + TARGETS ${XNCORE_LIB_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) diff --git a/Source/XnCore/XnBuffer.cpp b/Source/XnCore/XnBuffer.cpp index 5119aa3..32ed978 100644 --- a/Source/XnCore/XnBuffer.cpp +++ b/Source/XnCore/XnBuffer.cpp @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnBuffer.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnBuffer::Allocate(XnUInt32 nAllocSize) -{ - Free(); - XN_VALIDATE_ALIGNED_CALLOC(m_pData, XnUChar, nAllocSize, XN_DEFAULT_MEM_ALIGN); - m_nMaxSize = nAllocSize; - m_nSize = 0; - m_bAllocated = TRUE; - return (XN_STATUS_OK); -} - -void XnBuffer::SetExternalBuffer(XnUChar* pBuffer, XnUInt32 nSize) -{ - Free(); - m_pData = pBuffer; - m_nMaxSize = nSize; - m_nSize = 0; - m_bAllocated = FALSE; -} - -XnStatus XnBuffer::Write(const XnUChar* pData, XnUInt32 nDataSize) -{ - if (GetFreeSpaceInBuffer() < nDataSize) - return XN_STATUS_INTERNAL_BUFFER_TOO_SMALL; - - UnsafeWrite(pData, nDataSize); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnBuffer.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnBuffer::Allocate(XnUInt32 nAllocSize) +{ + Free(); + XN_VALIDATE_ALIGNED_CALLOC(m_pData, XnUChar, nAllocSize, XN_DEFAULT_MEM_ALIGN); + m_nMaxSize = nAllocSize; + m_nSize = 0; + m_bAllocated = TRUE; + return (XN_STATUS_OK); +} + +void XnBuffer::SetExternalBuffer(XnUChar* pBuffer, XnUInt32 nSize) +{ + Free(); + m_pData = pBuffer; + m_nMaxSize = nSize; + m_nSize = 0; + m_bAllocated = FALSE; +} + +XnStatus XnBuffer::Write(const XnUChar* pData, XnUInt32 nDataSize) +{ + if (GetFreeSpaceInBuffer() < nDataSize) + return XN_STATUS_INTERNAL_BUFFER_TOO_SMALL; + + UnsafeWrite(pData, nDataSize); + + return (XN_STATUS_OK); +} diff --git a/Source/XnCore/XnBuffer.h b/Source/XnCore/XnBuffer.h index 3b32ec7..aba1a0d 100644 --- a/Source/XnCore/XnBuffer.h +++ b/Source/XnCore/XnBuffer.h @@ -1,171 +1,171 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_BUFFER_H__ -#define __XN_BUFFER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -/** -* Holds a buffer of data, and provides some common methods for it. -*/ -class XN_CORE_CPP_API XnBuffer -{ -public: - XnBuffer() : m_pData(NULL), m_nMaxSize(0), m_nSize(0), m_bAllocated(FALSE) {} - ~XnBuffer() { Free(); } - - /* - * Allocates a buffer (aligned to default). - * - * @param size [in] The number of bytes to allocate. - */ - XnStatus Allocate(XnUInt32 nAllocSize); - - /** - * Sets an external buffer (instead of allocating) - * - * @param pBuffer [in] the buffer to use. - * @param nSize [in] Buffer size. - */ - void SetExternalBuffer(XnUChar* pBuffer, XnUInt32 nSize); - - /* - * Writes data to the buffer. - * - * @param data [in] a pointer to the data to copy from. - * @param size [in] The number of bytes to copy. - */ - inline void UnsafeWrite(const XnUChar* pData, XnUInt32 nDataSize) - { - xnOSMemCopy(m_pData + m_nSize, pData, nDataSize); - m_nSize += nDataSize; - } - - /* - * Writes data to the buffer, checking for free space - * - * @param data [in] a pointer to the data to copy from. - * @param size [in] The number of bytes to copy. - */ - XnStatus Write(const XnUChar* pData, XnUInt32 nDataSize); - - /* - * Copies buffer data to another location. - * - * @param dest [in] Location to write to. - */ - inline void UnsafeCopy(void* pDest) - { - xnOSMemCopy(pDest, m_pData, m_nSize); - } - - /* - * Empties the buffer. - */ - inline void Reset() - { - m_nSize = 0; - } - - inline const XnUChar* GetData() - { - return m_pData; - } - - inline XnUInt32 GetSize() - { - return m_nSize; - } - - inline XnUInt32 GetMaxSize() - { - return m_nMaxSize; - } - - /* - * Frees an allocated buffer. - */ - inline void Free() - { - if (m_bAllocated) - { - XN_ALIGNED_FREE_AND_NULL(m_pData); - m_bAllocated = FALSE; - } - } - - /* - * Gets the free space in the buffer. - */ - inline XnUInt32 GetFreeSpaceInBuffer() - { - return XN_MAX(0, (XnInt32)(m_nMaxSize - m_nSize)); - } - - /* - * Gets the free space in the buffer. - */ - inline XnUChar* GetUnsafeWritePointer() - { - return m_pData + m_nSize; - } - - /* - * Updates the size of the buffer - */ - inline void UnsafeUpdateSize(XnUInt32 nWrittenBytes) - { - m_nSize += nWrittenBytes; - } - -private: - XnUChar* m_pData; - XnUInt32 m_nSize; - XnUInt32 m_nMaxSize; - XnBool m_bAllocated; -}; - -/* -* Allocates a buffer (aligned to default), and validates that allocation succeeded. -* -* @param buf [in] The buffer to allocate. -* @param size [in] The number of bytes to allocate. -*/ -#define XN_VALIDATE_BUFFER_ALLOCATE(buf, size) \ - { \ - XnStatus rc = buf.Allocate(size); \ - XN_IS_STATUS_OK(rc); \ - } - -#endif //__XN_BUFFER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_BUFFER_H__ +#define __XN_BUFFER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +/** +* Holds a buffer of data, and provides some common methods for it. +*/ +class XN_CORE_CPP_API XnBuffer +{ +public: + XnBuffer() : m_pData(NULL), m_nMaxSize(0), m_nSize(0), m_bAllocated(FALSE) {} + ~XnBuffer() { Free(); } + + /* + * Allocates a buffer (aligned to default). + * + * @param size [in] The number of bytes to allocate. + */ + XnStatus Allocate(XnUInt32 nAllocSize); + + /** + * Sets an external buffer (instead of allocating) + * + * @param pBuffer [in] the buffer to use. + * @param nSize [in] Buffer size. + */ + void SetExternalBuffer(XnUChar* pBuffer, XnUInt32 nSize); + + /* + * Writes data to the buffer. + * + * @param data [in] a pointer to the data to copy from. + * @param size [in] The number of bytes to copy. + */ + inline void UnsafeWrite(const XnUChar* pData, XnUInt32 nDataSize) + { + xnOSMemCopy(m_pData + m_nSize, pData, nDataSize); + m_nSize += nDataSize; + } + + /* + * Writes data to the buffer, checking for free space + * + * @param data [in] a pointer to the data to copy from. + * @param size [in] The number of bytes to copy. + */ + XnStatus Write(const XnUChar* pData, XnUInt32 nDataSize); + + /* + * Copies buffer data to another location. + * + * @param dest [in] Location to write to. + */ + inline void UnsafeCopy(void* pDest) + { + xnOSMemCopy(pDest, m_pData, m_nSize); + } + + /* + * Empties the buffer. + */ + inline void Reset() + { + m_nSize = 0; + } + + inline const XnUChar* GetData() + { + return m_pData; + } + + inline XnUInt32 GetSize() + { + return m_nSize; + } + + inline XnUInt32 GetMaxSize() + { + return m_nMaxSize; + } + + /* + * Frees an allocated buffer. + */ + inline void Free() + { + if (m_bAllocated) + { + XN_ALIGNED_FREE_AND_NULL(m_pData); + m_bAllocated = FALSE; + } + } + + /* + * Gets the free space in the buffer. + */ + inline XnUInt32 GetFreeSpaceInBuffer() + { + return XN_MAX(0, (XnInt32)(m_nMaxSize - m_nSize)); + } + + /* + * Gets the free space in the buffer. + */ + inline XnUChar* GetUnsafeWritePointer() + { + return m_pData + m_nSize; + } + + /* + * Updates the size of the buffer + */ + inline void UnsafeUpdateSize(XnUInt32 nWrittenBytes) + { + m_nSize += nWrittenBytes; + } + +private: + XnUChar* m_pData; + XnUInt32 m_nSize; + XnUInt32 m_nMaxSize; + XnBool m_bAllocated; +}; + +/* +* Allocates a buffer (aligned to default), and validates that allocation succeeded. +* +* @param buf [in] The buffer to allocate. +* @param size [in] The number of bytes to allocate. +*/ +#define XN_VALIDATE_BUFFER_ALLOCATE(buf, size) \ + { \ + XnStatus rc = buf.Allocate(size); \ + XN_IS_STATUS_OK(rc); \ + } + +#endif //__XN_BUFFER_H__ diff --git a/Source/XnCore/XnCore.cpp b/Source/XnCore/XnCore.cpp index 2462419..83ddddf 100644 --- a/Source/XnCore/XnCore.cpp +++ b/Source/XnCore/XnCore.cpp @@ -1,129 +1,129 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -// Note: See the XnIOGlobals.h file for global variables description -XnBool g_bXnCoreWasInit = FALSE; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! -XN_API_EXPORT_INIT() - -XN_CORE_API XnStatus XnInit() -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - - // Make sure the core subsystem is not already initialized - XN_VALIDATE_CORE_NOT_INIT(); - - // Initialize the OS subsystem - nRetVal = xnOSInit(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_OS_ALREADY_INIT) - { - return (nRetVal); - } - - // initialize log - nRetVal = xnLogInitSystem(); - XN_IS_STATUS_OK(nRetVal); - - // Mark the Xiron core subsystem initialization as successful - g_bXnCoreWasInit = TRUE; - - // All is good... - return (XN_STATUS_OK); -} - -XN_CORE_API XnStatus XnInitFromINIFile(const XnChar* cpINIFileName) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(cpINIFileName); - - // Call the real init function - nRetVal = XnInit(); - XN_IS_STATUS_OK(nRetVal); - - // initialize log - nRetVal = xnLogInitFromINIFile(cpINIFileName, XN_CORE_INI_SECTION); - XN_IS_STATUS_OK(nRetVal); - - // initialize profiling - nRetVal = xnProfilingInitFromINI(cpINIFileName, XN_CORE_INI_SECTION); - XN_IS_STATUS_OK(nRetVal); - - // All is good... - return (XN_STATUS_OK); -} - -XN_CORE_API XnStatus XnShutdown() -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - - // Check if the core subsystem is initialized - XN_VALIDATE_CORE_INIT(); - - // Shutdown the network subsystem - nRetVal = xnOSShutdownNetwork(); - XN_IS_STATUS_OK(nRetVal); - - // Shutdown the OS subsystem - nRetVal = xnOSShutdown(); - XN_IS_STATUS_OK(nRetVal); - - // Shutdown the Log subsystem - nRetVal = xnLogClose(); - XN_IS_STATUS_OK(nRetVal); - - // Shutdown the Profiling subsystem - nRetVal = xnProfilingShutdown(); - XN_IS_STATUS_OK(nRetVal); - - // Mark the Xiron core subsystem as not-initialized - g_bXnCoreWasInit = FALSE; - - // All is good... - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +// Note: See the XnIOGlobals.h file for global variables description +XnBool g_bXnCoreWasInit = FALSE; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! +XN_API_EXPORT_INIT() + +XN_CORE_API XnStatus XnInit() +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + + // Make sure the core subsystem is not already initialized + XN_VALIDATE_CORE_NOT_INIT(); + + // Initialize the OS subsystem + nRetVal = xnOSInit(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_OS_ALREADY_INIT) + { + return (nRetVal); + } + + // initialize log + nRetVal = xnLogInitSystem(); + XN_IS_STATUS_OK(nRetVal); + + // Mark the Xiron core subsystem initialization as successful + g_bXnCoreWasInit = TRUE; + + // All is good... + return (XN_STATUS_OK); +} + +XN_CORE_API XnStatus XnInitFromINIFile(const XnChar* cpINIFileName) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(cpINIFileName); + + // Call the real init function + nRetVal = XnInit(); + XN_IS_STATUS_OK(nRetVal); + + // initialize log + nRetVal = xnLogInitFromINIFile(cpINIFileName, XN_CORE_INI_SECTION); + XN_IS_STATUS_OK(nRetVal); + + // initialize profiling + nRetVal = xnProfilingInitFromINI(cpINIFileName, XN_CORE_INI_SECTION); + XN_IS_STATUS_OK(nRetVal); + + // All is good... + return (XN_STATUS_OK); +} + +XN_CORE_API XnStatus XnShutdown() +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + + // Check if the core subsystem is initialized + XN_VALIDATE_CORE_INIT(); + + // Shutdown the network subsystem + nRetVal = xnOSShutdownNetwork(); + XN_IS_STATUS_OK(nRetVal); + + // Shutdown the OS subsystem + nRetVal = xnOSShutdown(); + XN_IS_STATUS_OK(nRetVal); + + // Shutdown the Log subsystem + nRetVal = xnLogClose(); + XN_IS_STATUS_OK(nRetVal); + + // Shutdown the Profiling subsystem + nRetVal = xnProfilingShutdown(); + XN_IS_STATUS_OK(nRetVal); + + // Mark the Xiron core subsystem as not-initialized + g_bXnCoreWasInit = FALSE; + + // All is good... + return (XN_STATUS_OK); +} diff --git a/Source/XnCore/XnCoreGlobals.h b/Source/XnCore/XnCoreGlobals.h index d0a8198..e6c94b2 100644 --- a/Source/XnCore/XnCoreGlobals.h +++ b/Source/XnCore/XnCoreGlobals.h @@ -1,65 +1,65 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_COREGLOBALS_H_ -#define _XN_COREGLOBALS_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -/** The Xiron I/O INI section name. */ -#define XN_CORE_INI_SECTION "Core" - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -/** Was the Xiron Core subsystem successfully initialized? */ -extern XnBool g_bXnCoreWasInit; - -//--------------------------------------------------------------------------- -// Macros -//--------------------------------------------------------------------------- -/** Make sure the core subsystem was initialized. */ -#define XN_VALIDATE_CORE_INIT() \ - if (g_bXnCoreWasInit != TRUE) \ - { \ - return (XN_STATUS_NOT_INIT); \ - } - -/** Make sure the core subsystem was not initialized already. */ -#define XN_VALIDATE_CORE_NOT_INIT() \ - if (g_bXnCoreWasInit == TRUE) \ - { \ - return (XN_STATUS_ALREADY_INIT); \ - } - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_COREGLOBALS_H_ +#define _XN_COREGLOBALS_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +/** The Xiron I/O INI section name. */ +#define XN_CORE_INI_SECTION "Core" + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +/** Was the Xiron Core subsystem successfully initialized? */ +extern XnBool g_bXnCoreWasInit; + +//--------------------------------------------------------------------------- +// Macros +//--------------------------------------------------------------------------- +/** Make sure the core subsystem was initialized. */ +#define XN_VALIDATE_CORE_INIT() \ + if (g_bXnCoreWasInit != TRUE) \ + { \ + return (XN_STATUS_NOT_INIT); \ + } + +/** Make sure the core subsystem was not initialized already. */ +#define XN_VALIDATE_CORE_NOT_INIT() \ + if (g_bXnCoreWasInit == TRUE) \ + { \ + return (XN_STATUS_ALREADY_INIT); \ + } + #endif //_XN_COREGLOBALS_H_ \ No newline at end of file diff --git a/Source/XnCore/XnCoreStatus.cpp b/Source/XnCore/XnCoreStatus.cpp index 40ea4e5..cbf7223 100644 --- a/Source/XnCore/XnCoreStatus.cpp +++ b/Source/XnCore/XnCoreStatus.cpp @@ -1,34 +1,34 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -// registration is done by including XnStatusRegister *before* including the list of errors -#include -#define XN_MESSAGE_MAP_REGISTER -#include "XnCore.h" +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +// registration is done by including XnStatusRegister *before* including the list of errors +#include +#define XN_MESSAGE_MAP_REGISTER +#include "XnCore.h" diff --git a/Source/XnCore/XnIOFileStream.cpp b/Source/XnCore/XnIOFileStream.cpp index 4c11580..bd4aa2f 100644 --- a/Source/XnCore/XnIOFileStream.cpp +++ b/Source/XnCore/XnIOFileStream.cpp @@ -1,85 +1,85 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnIOFileStream::XnIOFileStream(const XnChar* pcsFileName, XnUInt32 nFlags) : - m_pcsFileName(pcsFileName), m_nFlags(nFlags) -{ -} - -XnStatus XnIOFileStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSOpenFile(m_pcsFileName, m_nFlags, &m_hFile); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnIOFileStream::Free() -{ - return xnOSCloseFile(&m_hFile); -} - -XnStatus XnIOFileStream::WriteData(const XnUChar *pData, XnUInt32 nDataSize) -{ - return xnOSWriteFile(m_hFile, pData, nDataSize); -} - -XnStatus XnIOFileStream::ReadData(XnUChar *pData, XnUInt32 nDataSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nReadSize = nDataSize; - nRetVal = xnOSReadFile(m_hFile, pData, &nReadSize); - XN_IS_STATUS_OK(nRetVal); - - if (nReadSize != nDataSize) - { - return XN_STATUS_OS_FILE_READ_FAILED; - } - - return (XN_STATUS_OK); -} - -XnStatus XnIOFileStream::Tell(XnUInt32* pnOffset) -{ - return xnOSTellFile(m_hFile, pnOffset); -} - -XnStatus XnIOFileStream::Seek(XnUInt32 nOffset) -{ - return xnOSSeekFile(m_hFile, XN_OS_SEEK_SET, nOffset); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnIOFileStream::XnIOFileStream(const XnChar* pcsFileName, XnUInt32 nFlags) : + m_pcsFileName(pcsFileName), m_nFlags(nFlags) +{ +} + +XnStatus XnIOFileStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSOpenFile(m_pcsFileName, m_nFlags, &m_hFile); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnIOFileStream::Free() +{ + return xnOSCloseFile(&m_hFile); +} + +XnStatus XnIOFileStream::WriteData(const XnUChar *pData, XnUInt32 nDataSize) +{ + return xnOSWriteFile(m_hFile, pData, nDataSize); +} + +XnStatus XnIOFileStream::ReadData(XnUChar *pData, XnUInt32 nDataSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nReadSize = nDataSize; + nRetVal = xnOSReadFile(m_hFile, pData, &nReadSize); + XN_IS_STATUS_OK(nRetVal); + + if (nReadSize != nDataSize) + { + return XN_STATUS_OS_FILE_READ_FAILED; + } + + return (XN_STATUS_OK); +} + +XnStatus XnIOFileStream::Tell(XnUInt32* pnOffset) +{ + return xnOSTellFile(m_hFile, pnOffset); +} + +XnStatus XnIOFileStream::Seek(XnUInt32 nOffset) +{ + return xnOSSeekFile(m_hFile, XN_OS_SEEK_SET, nOffset); +} diff --git a/Source/XnCore/XnIONetworkStream.cpp b/Source/XnCore/XnIONetworkStream.cpp index b154043..d5cb3a3 100644 --- a/Source/XnCore/XnIONetworkStream.cpp +++ b/Source/XnCore/XnIONetworkStream.cpp @@ -1,108 +1,108 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnIONetworkStream.h" -#include - -#define XN_MASK_IO_NET_STREAM "IoNetStream" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnIONetworkStream::XnIONetworkStream(XN_SOCKET_HANDLE hSocket) : - m_hSocket(hSocket), - m_bIsConnected(TRUE), - m_nReadTimeout(XN_WAIT_INFINITE) -{ -} - -XnStatus XnIONetworkStream::Init() -{ - return (XN_STATUS_OK); -} - -XnStatus XnIONetworkStream::Free() -{ - m_bIsConnected = FALSE; - //We don't close the socket here because we don't own it - whoever opened it should be the one to close it. - return XN_STATUS_OK; -} - -XnStatus XnIONetworkStream::WriteData(const XnUChar *pData, XnUInt32 nDataSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSSendNetworkBuffer(m_hSocket, (const XnChar*)pData, nDataSize); - if (nRetVal != XN_STATUS_OK) - { - m_bIsConnected = FALSE; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnIONetworkStream::ReadData(XnUChar *pData, XnUInt32 nDataSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nTotalRead = 0; - - // read until we get all the data we want - while (nTotalRead < nDataSize) - { - XnUInt32 nReadSize = nDataSize - nTotalRead; - nRetVal = xnOSReceiveNetworkBuffer(m_hSocket, (XnChar*)(pData + nTotalRead), &nReadSize, m_nReadTimeout); - if (nRetVal != XN_STATUS_OK) - { - if (nRetVal == XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) - { - xnLogVerbose(XN_MASK_IO_NET_STREAM, "Network connection was closed gracefully"); - m_bIsConnected = FALSE; - } - else if (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT) - { - xnLogError(XN_MASK_IO_NET_STREAM, "Got an error while reading network buffer: %s", xnGetStatusString(nRetVal)); - m_bIsConnected = FALSE; - } - return (nRetVal); - } - - nTotalRead += nReadSize; - } - - return (XN_STATUS_OK); -} - - -void XnIONetworkStream::SetReadTimeout(XnUInt32 nMicrosecondsReadTimeout) -{ - m_nReadTimeout = nMicrosecondsReadTimeout; +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnIONetworkStream.h" +#include + +#define XN_MASK_IO_NET_STREAM "IoNetStream" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnIONetworkStream::XnIONetworkStream(XN_SOCKET_HANDLE hSocket) : + m_hSocket(hSocket), + m_bIsConnected(TRUE), + m_nReadTimeout(XN_WAIT_INFINITE) +{ +} + +XnStatus XnIONetworkStream::Init() +{ + return (XN_STATUS_OK); +} + +XnStatus XnIONetworkStream::Free() +{ + m_bIsConnected = FALSE; + //We don't close the socket here because we don't own it - whoever opened it should be the one to close it. + return XN_STATUS_OK; +} + +XnStatus XnIONetworkStream::WriteData(const XnUChar *pData, XnUInt32 nDataSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSSendNetworkBuffer(m_hSocket, (const XnChar*)pData, nDataSize); + if (nRetVal != XN_STATUS_OK) + { + m_bIsConnected = FALSE; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnIONetworkStream::ReadData(XnUChar *pData, XnUInt32 nDataSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nTotalRead = 0; + + // read until we get all the data we want + while (nTotalRead < nDataSize) + { + XnUInt32 nReadSize = nDataSize - nTotalRead; + nRetVal = xnOSReceiveNetworkBuffer(m_hSocket, (XnChar*)(pData + nTotalRead), &nReadSize, m_nReadTimeout); + if (nRetVal != XN_STATUS_OK) + { + if (nRetVal == XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) + { + xnLogVerbose(XN_MASK_IO_NET_STREAM, "Network connection was closed gracefully"); + m_bIsConnected = FALSE; + } + else if (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT) + { + xnLogError(XN_MASK_IO_NET_STREAM, "Got an error while reading network buffer: %s", xnGetStatusString(nRetVal)); + m_bIsConnected = FALSE; + } + return (nRetVal); + } + + nTotalRead += nReadSize; + } + + return (XN_STATUS_OK); +} + + +void XnIONetworkStream::SetReadTimeout(XnUInt32 nMicrosecondsReadTimeout) +{ + m_nReadTimeout = nMicrosecondsReadTimeout; } \ No newline at end of file diff --git a/Source/XnCore/XnVersion.cpp b/Source/XnCore/XnVersion.cpp index 8df08aa..2630354 100644 --- a/Source/XnCore/XnVersion.cpp +++ b/Source/XnCore/XnVersion.cpp @@ -1,47 +1,47 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_CORE_API XnUInt32 XnGetVersion(void) -{ - // Return the numeric version of Xiron version - return (XN_VERSION); -} - -XN_CORE_API const XnChar* XnGetVersionString(void) -{ - // Return the string version of Xiron version - return (XN_VERSION_STRING); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_CORE_API XnUInt32 XnGetVersion(void) +{ + // Return the numeric version of Xiron version + return (XN_VERSION); +} + +XN_CORE_API const XnChar* XnGetVersionString(void) +{ + // Return the string version of Xiron version + return (XN_VERSION_STRING); +} diff --git a/Source/XnDDK/CMakeLists.txt b/Source/XnDDK/CMakeLists.txt new file mode 100644 index 0000000..f2d7b51 --- /dev/null +++ b/Source/XnDDK/CMakeLists.txt @@ -0,0 +1,46 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR} + ${XNCORE_INCLUDE_DIR} + ../ +) + +# Get sources +# ------------ +file(GLOB ${XNDDK_LIB_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_library( + ${XNDDK_LIB_NAME} + SHARED + ${${XNDDK_LIB_NAME}_sources} +) + +target_link_libraries( + ${XNDDK_LIB_NAME} + ${XNCORE_LIB_NAME} + ${OPENNI_NIMCODECS_LIB_NAME} + ${LIBJPEG_LIB_NAME} + ${XNFORMAT_LIB_NAME} +) + +# The install_name is Mac OSX specific and is used to set the RPATH on a executable +# On Mac OSX the library can hold information for the rpath of the executable which +# uses the library. +# ---------------------------------------------------------------------------------- +if(SENSOR_PLATFORM_MAC) + set_target_properties(${XNDDK_LIB_NAME} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR ${INSTALL_NAME_VALUE} + ) +endif() + +# Set install dir +# --------------- +install( + TARGETS ${XNDDK_LIB_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) + diff --git a/Source/XnDDK/IXnDevice.h b/Source/XnDDK/IXnDevice.h index 5cc4308..9f69079 100644 --- a/Source/XnDDK/IXnDevice.h +++ b/Source/XnDDK/IXnDevice.h @@ -1,353 +1,353 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __IXN_DEVICE_BASE_H__ -#define __IXN_DEVICE_BASE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API IXnDevice -{ -public: - IXnDevice() {} - virtual ~IXnDevice() {} - - inline XnDeviceHandle GetDeviceHandle() const { return (XnDeviceHandle)this; } - static inline IXnDevice* GetFromDeviceHandle(XnDeviceHandle DeviceHandle) { return (IXnDevice*)(DeviceHandle); } - - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) = 0; - virtual XnStatus Destroy() = 0; - - /** - * Returns the types of the streams supported by this device. - * - * @param aStreamName [in/out] An array of stream names. Will be filled by the function. - * @param pnStreamNamesCount [in/out] The size of the array. Upon successful return, will contain the number of elements written to the array. - */ - virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) = 0; - - /** - * Creates a new stream in the device. - * - * @param StreamType [in] The type of the stream to create (one of the types returned by XnDeviceEnumerateStreams). - * @param StreamName [in] [Optional] A name for the new stream. - * @param pInitialValues [in] [Optional] A set of initial values for properties. - */ - virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) = 0; - - /** - * Destroys a previously created stream. - * - * @param StreamName [in] The name of the stream to destroy. - */ - virtual XnStatus DestroyStream(const XnChar* StreamName) = 0; - - /** - * Opens a stream for I/O operations. - * - * @param StreamName [in] The name of the stream to open. - */ - virtual XnStatus OpenStream(const XnChar* StreamName) = 0; - - /** - * Closes an open stream. - * - * @param StreamName [in] The name of the stream to close. - */ - virtual XnStatus CloseStream(const XnChar* StreamName) = 0; - - /** - * Get a list of all the streams that exist in the device. - * - * @param pstrStreamNames [in/out] An array of stream names. Will be filled by the function. - * @param pnNamesCount [in/out] The size of the array. Upon successful return, will contain the number of elements written to the array. - */ - virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) = 0; - - /** - * Checks if a specific module exists in this device. - * - * @param ModuleName [in] The name of the module to look for. - * @param pbDoesExist [out] TRUE if the module exists, FALSE otherwise. - */ - virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) = 0; - - /** - * Opens all closed streams. - */ - virtual XnStatus OpenAllStreams() = 0; - - /** - * Closes all open streams. - */ - virtual XnStatus CloseAllStreams() = 0; - - /** - * Registers to the event of streams change (stream created / destroyed) - * - * @param Handler [in] A pointer to the function that will handle the event. - * @param pCookie [in] User cookie that will be passed as an argument to the event handler. - * @param phCallback [out] A handle for unregister. - */ - virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; - - /** - * Unregisters from the event of streams change (stream created / destroyed) - * - * @param hCallback [in] The handle returned from RegisterToStreamsChange. - */ - virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) = 0; - - /** - * Creates a stream data object for the requested stream. - * - * @param StreamName [in] The requested stream. - * @param ppStreamData [out] The created stream data object. - */ - virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) = 0; - - /** - * Registers to the event of new data from a stream. - * - * @param Handler [in] A pointer to the function that will handle the event. - * @param pCookie [in] User cookie that will be passed as an argument to the event handler. - * @param phCallback [out] A handle for unregister. - */ - virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; - - /** - * Unregisters from the event of new data from a stream. - * - * @param hCallback [in] The handle returned from RegisterToNewStreamData. - */ - virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) = 0; - - /** - * Checks if new data is available from stream. - * - * @param StreamName [in] The name of the stream to check. - * @param pbNewDataAvailable [out] TRUE if new data is available, FALSE otherwise. - */ - virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) = 0; - - /** - * Waits for new data to be available from requested stream, and then return it. - * - * @param pStreamOutput [in/out] A stream output object. The function will use the stream output object to determine which stream to read. - */ - virtual XnStatus ReadStream(XnStreamData* pStreamOutput) = 0; - - /** - * Waits for new data from the primary stream to be available, and then reads all requested streams. - * - * @param pStreamOutputSet [in/out] A set of stream output objects. - */ - virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) = 0; - - /** - * Writes a single stream data to the device. - * - * @param pStreamOutput [in] A stream output object. - */ - virtual XnStatus WriteStream(XnStreamData* pStreamOutput) = 0; - - /** - * Writes multiple streams to the device. - * - * @param pStreamOutputSet [in] A set of stream output objects. - */ - virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) = 0; - - /** - * Gets current position of the device. - * - * @param pnTimestamp [out] Current device timestamp. - */ - virtual XnStatus Tell(XnUInt64* pnTimestamp) = 0; - - /** - * Seeks the device to the requested position. - * - * @param nTimestamp [in] Requested device timestamp. - */ - virtual XnStatus Seek(XnUInt64 nTimestamp) = 0; - - /** - * Gets current frame position of the device. - * - * @param DeviceHandle [in] The requested device handle. - * @param pnFrameID [out] Current device frame. - */ - virtual XnStatus TellFrame(XnUInt32* pnFrameID) = 0; - - /** - * Seeks the device to the requested frame position. - * - * @param DeviceHandle [in] The requested device handle. - * @param nFrameID [in] Requested device frame. - */ - virtual XnStatus SeekFrame(XnUInt32 nFrameID) = 0; - - /** - * Checks if a specific property exists in a module. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param pbDoesExist [out] TRUE if the property exists, FALSE otherwise. - */ - virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) = 0; - - /** - * Returns the type of a specific property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param pnType [out] Type of this property. - */ - virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) = 0; - - /** - * Sets the value of an int property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param nValue [in] New requested value. - */ - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) = 0; - - /** - * Sets the value of a real property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param dValue [in] New requested value. - */ - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) = 0; - - /** - * Sets the value of a string property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param csValue [in] New requested value. - */ - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) = 0; - - /** - * Sets the value of a general property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param gbValue [in] New requested value. - */ - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) = 0; - - /** - * Gets the value of an int property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param pnValue [out] Current value. - */ - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) = 0; - - /** - * Gets the value of a real property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param pdValue [out] Current value. - */ - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) = 0; - - /** - * Gets the value of a string property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param csValue [in/out] Current value. The passed buffer should be of size XN_DEVICE_MAX_STRING_LENGTH. - */ - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) = 0; - - /** - * Gets the value of a general property. - * - * @param ModuleName [in] Name of the module. - * @param PropertyName [in] Name of the property to change. - * @param gbValue [out] A buffer to fill. - */ - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) = 0; - - /** - * Loads configuration from INI file. - * - * @param csINIFilePath [in] A path to the INI file. - * @param csSectionName [in] The name of the section containing configuration. - */ - virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) = 0; - - /** - * Batch-Configures device. All the properties in the set will be set as a single transaction. - * - * @param pChangeSet [in] A set of properties to be changed. - */ - virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet) = 0; - - /** - * Gets all the properties of a device. - * - * @param pSet [in] The property set to be filled. - */ - virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) = 0; - - /** - * Registers an event handler to the Property Changed event of a specific property. - * - * @param Module [in] Name of the module. - * @param PropertyName [in] Name of the property to register to. - * @param Handler [in] A pointer to the function that will handle the event. - * @param pCookie [in] User cookie that will be passed as an argument to the event handler. - * @param phCallback [out] A handle for unregister. - */ - virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; - - /** - * Unregisters an event handler from the Property Changed event. - * - * @param Module [in] Name of the module. - * @param PropertyName [in] Name of the property to register to. - * @param hCallback [in] The handle returned from RegisterToNewStreamData. - */ - virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) = 0; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __IXN_DEVICE_BASE_H__ +#define __IXN_DEVICE_BASE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API IXnDevice +{ +public: + IXnDevice() {} + virtual ~IXnDevice() {} + + inline XnDeviceHandle GetDeviceHandle() const { return (XnDeviceHandle)this; } + static inline IXnDevice* GetFromDeviceHandle(XnDeviceHandle DeviceHandle) { return (IXnDevice*)(DeviceHandle); } + + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) = 0; + virtual XnStatus Destroy() = 0; + + /** + * Returns the types of the streams supported by this device. + * + * @param aStreamName [in/out] An array of stream names. Will be filled by the function. + * @param pnStreamNamesCount [in/out] The size of the array. Upon successful return, will contain the number of elements written to the array. + */ + virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) = 0; + + /** + * Creates a new stream in the device. + * + * @param StreamType [in] The type of the stream to create (one of the types returned by XnDeviceEnumerateStreams). + * @param StreamName [in] [Optional] A name for the new stream. + * @param pInitialValues [in] [Optional] A set of initial values for properties. + */ + virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) = 0; + + /** + * Destroys a previously created stream. + * + * @param StreamName [in] The name of the stream to destroy. + */ + virtual XnStatus DestroyStream(const XnChar* StreamName) = 0; + + /** + * Opens a stream for I/O operations. + * + * @param StreamName [in] The name of the stream to open. + */ + virtual XnStatus OpenStream(const XnChar* StreamName) = 0; + + /** + * Closes an open stream. + * + * @param StreamName [in] The name of the stream to close. + */ + virtual XnStatus CloseStream(const XnChar* StreamName) = 0; + + /** + * Get a list of all the streams that exist in the device. + * + * @param pstrStreamNames [in/out] An array of stream names. Will be filled by the function. + * @param pnNamesCount [in/out] The size of the array. Upon successful return, will contain the number of elements written to the array. + */ + virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) = 0; + + /** + * Checks if a specific module exists in this device. + * + * @param ModuleName [in] The name of the module to look for. + * @param pbDoesExist [out] TRUE if the module exists, FALSE otherwise. + */ + virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) = 0; + + /** + * Opens all closed streams. + */ + virtual XnStatus OpenAllStreams() = 0; + + /** + * Closes all open streams. + */ + virtual XnStatus CloseAllStreams() = 0; + + /** + * Registers to the event of streams change (stream created / destroyed) + * + * @param Handler [in] A pointer to the function that will handle the event. + * @param pCookie [in] User cookie that will be passed as an argument to the event handler. + * @param phCallback [out] A handle for unregister. + */ + virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; + + /** + * Unregisters from the event of streams change (stream created / destroyed) + * + * @param hCallback [in] The handle returned from RegisterToStreamsChange. + */ + virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) = 0; + + /** + * Creates a stream data object for the requested stream. + * + * @param StreamName [in] The requested stream. + * @param ppStreamData [out] The created stream data object. + */ + virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) = 0; + + /** + * Registers to the event of new data from a stream. + * + * @param Handler [in] A pointer to the function that will handle the event. + * @param pCookie [in] User cookie that will be passed as an argument to the event handler. + * @param phCallback [out] A handle for unregister. + */ + virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; + + /** + * Unregisters from the event of new data from a stream. + * + * @param hCallback [in] The handle returned from RegisterToNewStreamData. + */ + virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) = 0; + + /** + * Checks if new data is available from stream. + * + * @param StreamName [in] The name of the stream to check. + * @param pbNewDataAvailable [out] TRUE if new data is available, FALSE otherwise. + */ + virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) = 0; + + /** + * Waits for new data to be available from requested stream, and then return it. + * + * @param pStreamOutput [in/out] A stream output object. The function will use the stream output object to determine which stream to read. + */ + virtual XnStatus ReadStream(XnStreamData* pStreamOutput) = 0; + + /** + * Waits for new data from the primary stream to be available, and then reads all requested streams. + * + * @param pStreamOutputSet [in/out] A set of stream output objects. + */ + virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) = 0; + + /** + * Writes a single stream data to the device. + * + * @param pStreamOutput [in] A stream output object. + */ + virtual XnStatus WriteStream(XnStreamData* pStreamOutput) = 0; + + /** + * Writes multiple streams to the device. + * + * @param pStreamOutputSet [in] A set of stream output objects. + */ + virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) = 0; + + /** + * Gets current position of the device. + * + * @param pnTimestamp [out] Current device timestamp. + */ + virtual XnStatus Tell(XnUInt64* pnTimestamp) = 0; + + /** + * Seeks the device to the requested position. + * + * @param nTimestamp [in] Requested device timestamp. + */ + virtual XnStatus Seek(XnUInt64 nTimestamp) = 0; + + /** + * Gets current frame position of the device. + * + * @param DeviceHandle [in] The requested device handle. + * @param pnFrameID [out] Current device frame. + */ + virtual XnStatus TellFrame(XnUInt32* pnFrameID) = 0; + + /** + * Seeks the device to the requested frame position. + * + * @param DeviceHandle [in] The requested device handle. + * @param nFrameID [in] Requested device frame. + */ + virtual XnStatus SeekFrame(XnUInt32 nFrameID) = 0; + + /** + * Checks if a specific property exists in a module. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param pbDoesExist [out] TRUE if the property exists, FALSE otherwise. + */ + virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) = 0; + + /** + * Returns the type of a specific property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param pnType [out] Type of this property. + */ + virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) = 0; + + /** + * Sets the value of an int property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param nValue [in] New requested value. + */ + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) = 0; + + /** + * Sets the value of a real property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param dValue [in] New requested value. + */ + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) = 0; + + /** + * Sets the value of a string property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param csValue [in] New requested value. + */ + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) = 0; + + /** + * Sets the value of a general property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param gbValue [in] New requested value. + */ + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) = 0; + + /** + * Gets the value of an int property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param pnValue [out] Current value. + */ + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) = 0; + + /** + * Gets the value of a real property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param pdValue [out] Current value. + */ + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) = 0; + + /** + * Gets the value of a string property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param csValue [in/out] Current value. The passed buffer should be of size XN_DEVICE_MAX_STRING_LENGTH. + */ + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) = 0; + + /** + * Gets the value of a general property. + * + * @param ModuleName [in] Name of the module. + * @param PropertyName [in] Name of the property to change. + * @param gbValue [out] A buffer to fill. + */ + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) = 0; + + /** + * Loads configuration from INI file. + * + * @param csINIFilePath [in] A path to the INI file. + * @param csSectionName [in] The name of the section containing configuration. + */ + virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) = 0; + + /** + * Batch-Configures device. All the properties in the set will be set as a single transaction. + * + * @param pChangeSet [in] A set of properties to be changed. + */ + virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet) = 0; + + /** + * Gets all the properties of a device. + * + * @param pSet [in] The property set to be filled. + */ + virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) = 0; + + /** + * Registers an event handler to the Property Changed event of a specific property. + * + * @param Module [in] Name of the module. + * @param PropertyName [in] Name of the property to register to. + * @param Handler [in] A pointer to the function that will handle the event. + * @param pCookie [in] User cookie that will be passed as an argument to the event handler. + * @param phCallback [out] A handle for unregister. + */ + virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) = 0; + + /** + * Unregisters an event handler from the Property Changed event. + * + * @param Module [in] Name of the module. + * @param PropertyName [in] Name of the property to register to. + * @param hCallback [in] The handle returned from RegisterToNewStreamData. + */ + virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) = 0; +}; + #endif //__IXN_DEVICE_BASE_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnActualGeneralProperty.cpp b/Source/XnDDK/XnActualGeneralProperty.cpp index cd9c398..74eb2ae 100644 --- a/Source/XnDDK/XnActualGeneralProperty.cpp +++ b/Source/XnDDK/XnActualGeneralProperty.cpp @@ -1,92 +1,92 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnActualGeneralProperty.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnActualGeneralProperty::XnActualGeneralProperty(const XnChar* strName, void* pData, XnUInt32 nDataSize, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */) : - XnGeneralProperty(strName, &m_gbValue, pReadFromFileFunc, strModule), - m_gbValue(XnGeneralBufferPack(pData, nDataSize)), - m_bOwner(FALSE) -{ - // set a callback for get operations - UpdateGetCallback(GetCallback, this); -} - -XnActualGeneralProperty::XnActualGeneralProperty(const XnChar* strName, const XnGeneralBuffer& gbValue, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */) : - XnGeneralProperty(strName, &m_gbValue, pReadFromFileFunc, strModule), - m_gbValue(gbValue), - m_bOwner(FALSE) -{ - // set a callback for get operations - UpdateGetCallback(GetCallback, this); -} - -XnActualGeneralProperty::~XnActualGeneralProperty() -{ - if (m_bOwner) - { - XnGeneralBufferFree(&m_gbValue); - } -} - -void XnActualGeneralProperty::SetAsBufferOwner(XnBool bOwner) -{ - m_bOwner = bOwner; -} - -XnStatus XnActualGeneralProperty::SetCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - return pSender->UnsafeUpdateValue(gbValue); -} - -XnStatus XnActualGeneralProperty::GetCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - if (gbValue.nDataSize != pSender->GetValue().nDataSize) - { - return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; - } - - xnOSMemCopy(gbValue.pData, pSender->GetValue().pData, pSender->GetValue().nDataSize); - return XN_STATUS_OK; -} - -XnStatus XnActualGeneralProperty::AddToPropertySet(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnPropertySetAddGeneralProperty(pSet, GetModule(), GetName(), &m_gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnActualGeneralProperty.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnActualGeneralProperty::XnActualGeneralProperty(const XnChar* strName, void* pData, XnUInt32 nDataSize, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */) : + XnGeneralProperty(strName, &m_gbValue, pReadFromFileFunc, strModule), + m_gbValue(XnGeneralBufferPack(pData, nDataSize)), + m_bOwner(FALSE) +{ + // set a callback for get operations + UpdateGetCallback(GetCallback, this); +} + +XnActualGeneralProperty::XnActualGeneralProperty(const XnChar* strName, const XnGeneralBuffer& gbValue, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */) : + XnGeneralProperty(strName, &m_gbValue, pReadFromFileFunc, strModule), + m_gbValue(gbValue), + m_bOwner(FALSE) +{ + // set a callback for get operations + UpdateGetCallback(GetCallback, this); +} + +XnActualGeneralProperty::~XnActualGeneralProperty() +{ + if (m_bOwner) + { + XnGeneralBufferFree(&m_gbValue); + } +} + +void XnActualGeneralProperty::SetAsBufferOwner(XnBool bOwner) +{ + m_bOwner = bOwner; +} + +XnStatus XnActualGeneralProperty::SetCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + return pSender->UnsafeUpdateValue(gbValue); +} + +XnStatus XnActualGeneralProperty::GetCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + if (gbValue.nDataSize != pSender->GetValue().nDataSize) + { + return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; + } + + xnOSMemCopy(gbValue.pData, pSender->GetValue().pData, pSender->GetValue().nDataSize); + return XN_STATUS_OK; +} + +XnStatus XnActualGeneralProperty::AddToPropertySet(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnPropertySetAddGeneralProperty(pSet, GetModule(), GetName(), &m_gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnActualGeneralProperty.h b/Source/XnDDK/XnActualGeneralProperty.h index 1c9f5ab..d149984 100644 --- a/Source/XnDDK/XnActualGeneralProperty.h +++ b/Source/XnDDK/XnActualGeneralProperty.h @@ -1,87 +1,87 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_ACTUAL_GENERAL_PROPERTY_H__ -#define __XN_ACTUAL_GENERAL_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type general which actually holds a value. -*/ -class XN_DDK_CPP_API XnActualGeneralProperty : public XnGeneralProperty -{ -public: - XnActualGeneralProperty(const XnChar* strName, void* pData, XnUInt32 nDataSize, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); - XnActualGeneralProperty(const XnChar* strName, const XnGeneralBuffer& gbValue, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); - ~XnActualGeneralProperty(); - - void SetAsBufferOwner(XnBool bOwner); - - inline const XnGeneralBuffer& GetValue() const { return m_gbValue; } - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnGeneralProperty::UpdateSetCallback((XnGeneralProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateSetCallbackToDefault() - { - UpdateSetCallback(SetCallback, this); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnGeneralProperty::UpdateGetCallback((XnGeneralProperty::GetFuncPtr)pFunc, pCookie); - } - - inline void ReplaceBuffer(void* pData, XnUInt32 nDataSize) - { - m_gbValue.pData = pData; - m_gbValue.nDataSize = nDataSize; - } - - XnStatus AddToPropertySet(XnPropertySet* pSet); - -private: - static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - - XnGeneralBuffer m_gbValue; - XnBool m_bOwner; -}; - -#endif //__XN_ACTUAL_GENERAL_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_ACTUAL_GENERAL_PROPERTY_H__ +#define __XN_ACTUAL_GENERAL_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type general which actually holds a value. +*/ +class XN_DDK_CPP_API XnActualGeneralProperty : public XnGeneralProperty +{ +public: + XnActualGeneralProperty(const XnChar* strName, void* pData, XnUInt32 nDataSize, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); + XnActualGeneralProperty(const XnChar* strName, const XnGeneralBuffer& gbValue, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); + ~XnActualGeneralProperty(); + + void SetAsBufferOwner(XnBool bOwner); + + inline const XnGeneralBuffer& GetValue() const { return m_gbValue; } + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnGeneralProperty::UpdateSetCallback((XnGeneralProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateSetCallbackToDefault() + { + UpdateSetCallback(SetCallback, this); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnGeneralProperty::UpdateGetCallback((XnGeneralProperty::GetFuncPtr)pFunc, pCookie); + } + + inline void ReplaceBuffer(void* pData, XnUInt32 nDataSize) + { + m_gbValue.pData = pData; + m_gbValue.nDataSize = nDataSize; + } + + XnStatus AddToPropertySet(XnPropertySet* pSet); + +private: + static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + + XnGeneralBuffer m_gbValue; + XnBool m_bOwner; +}; + +#endif //__XN_ACTUAL_GENERAL_PROPERTY_H__ diff --git a/Source/XnDDK/XnActualIntProperty.cpp b/Source/XnDDK/XnActualIntProperty.cpp index d9b26c2..acb9c24 100644 --- a/Source/XnDDK/XnActualIntProperty.cpp +++ b/Source/XnDDK/XnActualIntProperty.cpp @@ -1,53 +1,53 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnActualIntProperty.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnActualIntProperty::XnActualIntProperty(const XnChar* strName, XnUInt64 nInitialValue /* = 0 */, const XnChar* strModule /* = "" */) : - XnIntProperty(strName, &m_nValue, strModule), - m_nValue(nInitialValue) -{ - // set a callback for get operations - UpdateGetCallback(GetCallback, this); -} - -XnStatus XN_CALLBACK_TYPE XnActualIntProperty::SetCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - return pSender->UnsafeUpdateValue(nValue); -} - -XnStatus XN_CALLBACK_TYPE XnActualIntProperty::GetCallback(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie) -{ - *pnValue = pSender->GetValue(); - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnActualIntProperty.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnActualIntProperty::XnActualIntProperty(const XnChar* strName, XnUInt64 nInitialValue /* = 0 */, const XnChar* strModule /* = "" */) : + XnIntProperty(strName, &m_nValue, strModule), + m_nValue(nInitialValue) +{ + // set a callback for get operations + UpdateGetCallback(GetCallback, this); +} + +XnStatus XN_CALLBACK_TYPE XnActualIntProperty::SetCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + return pSender->UnsafeUpdateValue(nValue); +} + +XnStatus XN_CALLBACK_TYPE XnActualIntProperty::GetCallback(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie) +{ + *pnValue = pSender->GetValue(); + return XN_STATUS_OK; +} diff --git a/Source/XnDDK/XnActualIntProperty.h b/Source/XnDDK/XnActualIntProperty.h index dc90168..8b7b9a5 100644 --- a/Source/XnDDK/XnActualIntProperty.h +++ b/Source/XnDDK/XnActualIntProperty.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_ACTUAL_INT_PROPERTY_H__ -#define __XN_ACTUAL_INT_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* A property of type integer. -*/ -class XN_DDK_CPP_API XnActualIntProperty : public XnIntProperty -{ -public: - XnActualIntProperty(const XnChar* strName, XnUInt64 nInitialValue = 0, const XnChar* strModule = ""); - - inline XnUInt64 GetValue() const { return m_nValue; } - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie); - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnIntProperty::UpdateSetCallback((XnIntProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateSetCallbackToDefault() - { - UpdateSetCallback(SetCallback, this); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnIntProperty::UpdateGetCallback((XnIntProperty::GetFuncPtr)pFunc, pCookie); - } - -private: - static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie); - - XnUInt64 m_nValue; -}; - -#endif //__XN_ACTUAL_INT_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_ACTUAL_INT_PROPERTY_H__ +#define __XN_ACTUAL_INT_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* A property of type integer. +*/ +class XN_DDK_CPP_API XnActualIntProperty : public XnIntProperty +{ +public: + XnActualIntProperty(const XnChar* strName, XnUInt64 nInitialValue = 0, const XnChar* strModule = ""); + + inline XnUInt64 GetValue() const { return m_nValue; } + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie); + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnIntProperty::UpdateSetCallback((XnIntProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateSetCallbackToDefault() + { + UpdateSetCallback(SetCallback, this); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnIntProperty::UpdateGetCallback((XnIntProperty::GetFuncPtr)pFunc, pCookie); + } + +private: + static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualIntProperty* pSender, XnUInt64* pnValue, void* pCookie); + + XnUInt64 m_nValue; +}; + +#endif //__XN_ACTUAL_INT_PROPERTY_H__ diff --git a/Source/XnDDK/XnActualPropertiesHash.cpp b/Source/XnDDK/XnActualPropertiesHash.cpp index fcd0b1c..de23eff 100644 --- a/Source/XnDDK/XnActualPropertiesHash.cpp +++ b/Source/XnDDK/XnActualPropertiesHash.cpp @@ -1,242 +1,242 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#include "XnActualPropertiesHash.h" - -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" - -XnActualPropertiesHash::XnActualPropertiesHash(const XnChar* strName) -{ - strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); -} - -XnActualPropertiesHash::~XnActualPropertiesHash() -{ - // free all properties - for (Iterator it = begin(); it != end(); ++it) - { - XN_DELETE(it.Value()); - } -} - -XnStatus XnActualPropertiesHash::Add(const XnChar* strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Iterator it = end(); - if (XN_STATUS_OK == Find(strName, it)) - { - return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; - } - - // create property - XnActualIntProperty* pProp; - XN_VALIDATE_NEW(pProp, XnActualIntProperty, strName, nValue, m_strName); - - // and add it to the hash - nRetVal = m_Hash.Set(strName, pProp); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pProp); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Add(const XnChar* strName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Iterator it = end(); - if (XN_STATUS_OK == Find(strName, it)) - { - return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; - } - - // create property - XnActualRealProperty* pProp; - XN_VALIDATE_NEW(pProp, XnActualRealProperty, strName, dValue, m_strName); - - // and add it to the hash - nRetVal = m_Hash.Set(strName, pProp); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pProp); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Add(const XnChar* strName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Iterator it = end(); - if (XN_STATUS_OK == Find(strName, it)) - { - return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; - } - - // create property - XnActualStringProperty* pProp; - XN_VALIDATE_NEW(pProp, XnActualStringProperty, strName, strValue, m_strName); - - // and add it to the hash - nRetVal = m_Hash.Set(strName, pProp); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pProp); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Add(const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Iterator it = end(); - if (XN_STATUS_OK == Find(strName, it)) - { - return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; - } - - // create buffer - XnGeneralBuffer gbNew; - nRetVal = XnGeneralBufferAlloc(&gbNew, gbValue.nDataSize); - XN_IS_STATUS_OK(nRetVal); - - // copy content - xnOSMemCopy(gbNew.pData, gbValue.pData, gbValue.nDataSize); - - // create property - XnActualGeneralProperty* pProp; - XN_VALIDATE_NEW(pProp, XnActualGeneralProperty, strName, gbNew, NULL, m_strName); - - pProp->SetAsBufferOwner(TRUE); - - // and add it to the hash - nRetVal = m_Hash.Set(strName, pProp); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pProp); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Remove(const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pProp = NULL; - nRetVal = m_Hash.Remove(strName, pProp); - XN_IS_STATUS_OK(nRetVal); - - if (pProp != NULL) - { - XN_DELETE(pProp); - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Remove(ConstIterator where) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pProp = where.Value(); - - nRetVal = m_Hash.Remove(where); - XN_IS_STATUS_OK(nRetVal); - - XN_DELETE(pProp); - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertiesHash::Clear() -{ - while (!IsEmpty()) - { - Remove(begin()); - } - - return XN_STATUS_OK; -} - -XnStatus XnActualPropertiesHash::CopyFrom(const XnActualPropertiesHash& other) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Clear(); - strncpy(m_strName, other.m_strName, XN_DEVICE_MAX_STRING_LENGTH); - - for (ConstIterator it = other.begin(); it != other.end(); ++it) - { - switch (it.Value()->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pProp = (XnActualIntProperty*)it.Value(); - nRetVal = Add(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pProp = (XnActualRealProperty*)it.Value(); - nRetVal = Add(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pProp = (XnActualStringProperty*)it.Value(); - nRetVal = Add(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)it.Value(); - nRetVal = Add(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", it.Value()->GetType()); - } - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#include "XnActualPropertiesHash.h" + +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" + +XnActualPropertiesHash::XnActualPropertiesHash(const XnChar* strName) +{ + strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); +} + +XnActualPropertiesHash::~XnActualPropertiesHash() +{ + // free all properties + for (Iterator it = begin(); it != end(); ++it) + { + XN_DELETE(it.Value()); + } +} + +XnStatus XnActualPropertiesHash::Add(const XnChar* strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Iterator it = end(); + if (XN_STATUS_OK == Find(strName, it)) + { + return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; + } + + // create property + XnActualIntProperty* pProp; + XN_VALIDATE_NEW(pProp, XnActualIntProperty, strName, nValue, m_strName); + + // and add it to the hash + nRetVal = m_Hash.Set(strName, pProp); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pProp); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Add(const XnChar* strName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Iterator it = end(); + if (XN_STATUS_OK == Find(strName, it)) + { + return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; + } + + // create property + XnActualRealProperty* pProp; + XN_VALIDATE_NEW(pProp, XnActualRealProperty, strName, dValue, m_strName); + + // and add it to the hash + nRetVal = m_Hash.Set(strName, pProp); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pProp); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Add(const XnChar* strName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Iterator it = end(); + if (XN_STATUS_OK == Find(strName, it)) + { + return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; + } + + // create property + XnActualStringProperty* pProp; + XN_VALIDATE_NEW(pProp, XnActualStringProperty, strName, strValue, m_strName); + + // and add it to the hash + nRetVal = m_Hash.Set(strName, pProp); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pProp); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Add(const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Iterator it = end(); + if (XN_STATUS_OK == Find(strName, it)) + { + return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; + } + + // create buffer + XnGeneralBuffer gbNew; + nRetVal = XnGeneralBufferAlloc(&gbNew, gbValue.nDataSize); + XN_IS_STATUS_OK(nRetVal); + + // copy content + xnOSMemCopy(gbNew.pData, gbValue.pData, gbValue.nDataSize); + + // create property + XnActualGeneralProperty* pProp; + XN_VALIDATE_NEW(pProp, XnActualGeneralProperty, strName, gbNew, NULL, m_strName); + + pProp->SetAsBufferOwner(TRUE); + + // and add it to the hash + nRetVal = m_Hash.Set(strName, pProp); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pProp); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Remove(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pProp = NULL; + nRetVal = m_Hash.Remove(strName, pProp); + XN_IS_STATUS_OK(nRetVal); + + if (pProp != NULL) + { + XN_DELETE(pProp); + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Remove(ConstIterator where) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pProp = where.Value(); + + nRetVal = m_Hash.Remove(where); + XN_IS_STATUS_OK(nRetVal); + + XN_DELETE(pProp); + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertiesHash::Clear() +{ + while (!IsEmpty()) + { + Remove(begin()); + } + + return XN_STATUS_OK; +} + +XnStatus XnActualPropertiesHash::CopyFrom(const XnActualPropertiesHash& other) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Clear(); + strncpy(m_strName, other.m_strName, XN_DEVICE_MAX_STRING_LENGTH); + + for (ConstIterator it = other.begin(); it != other.end(); ++it) + { + switch (it.Value()->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pProp = (XnActualIntProperty*)it.Value(); + nRetVal = Add(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pProp = (XnActualRealProperty*)it.Value(); + nRetVal = Add(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pProp = (XnActualStringProperty*)it.Value(); + nRetVal = Add(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)it.Value(); + nRetVal = Add(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", it.Value()->GetType()); + } + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnActualPropertiesHash.h b/Source/XnDDK/XnActualPropertiesHash.h index 8d30852..349e202 100644 --- a/Source/XnDDK/XnActualPropertiesHash.h +++ b/Source/XnDDK/XnActualPropertiesHash.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_ACTUAL_PROPERTIES_HASH_H__ -#define __XN_ACTUAL_PROPERTIES_HASH_H__ - -#include "XnProperty.h" -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" - -/** -* A hash table of actual properties. The user can safely assume that every property in this -* hash is actual. -*/ -class XN_DDK_CPP_API XnActualPropertiesHash -{ -public: - XnActualPropertiesHash(const XnChar* strName); - ~XnActualPropertiesHash(); - - typedef XnPropertiesHash::Iterator Iterator; - typedef XnPropertiesHash::ConstIterator ConstIterator; - - XnStatus Add(const XnChar* strName, XnUInt64 nValue); - XnStatus Add(const XnChar* strName, XnDouble dValue); - XnStatus Add(const XnChar* strName, const XnChar* strValue); - XnStatus Add(const XnChar* strName, const XnGeneralBuffer& gbValue); - - XnStatus Remove(const XnChar* strName); - XnStatus Remove(ConstIterator where); - inline XnBool IsEmpty() const { return m_Hash.IsEmpty(); } - XnStatus Clear(); - - inline XnStatus Find(const XnChar* strName, Iterator& iter) { return m_Hash.Find(strName, iter); } - inline XnStatus Find(const XnChar* strName, ConstIterator& iter) const { return m_Hash.Find(strName, iter); } - inline XnStatus Get(const XnChar* strName, XnProperty*& pProp) const { return m_Hash.Get(strName, pProp); } - - inline Iterator begin() { return m_Hash.begin(); } - inline ConstIterator begin() const { return m_Hash.begin(); } - inline Iterator end() { return m_Hash.end(); } - inline ConstIterator end() const { return m_Hash.end(); } - - XnStatus CopyFrom(const XnActualPropertiesHash& other); - -protected: - XnPropertiesHash m_Hash; - XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; -}; - -#endif //__XN_ACTUAL_PROPERTIES_HASH_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_ACTUAL_PROPERTIES_HASH_H__ +#define __XN_ACTUAL_PROPERTIES_HASH_H__ + +#include "XnProperty.h" +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" + +/** +* A hash table of actual properties. The user can safely assume that every property in this +* hash is actual. +*/ +class XN_DDK_CPP_API XnActualPropertiesHash +{ +public: + XnActualPropertiesHash(const XnChar* strName); + ~XnActualPropertiesHash(); + + typedef XnPropertiesHash::Iterator Iterator; + typedef XnPropertiesHash::ConstIterator ConstIterator; + + XnStatus Add(const XnChar* strName, XnUInt64 nValue); + XnStatus Add(const XnChar* strName, XnDouble dValue); + XnStatus Add(const XnChar* strName, const XnChar* strValue); + XnStatus Add(const XnChar* strName, const XnGeneralBuffer& gbValue); + + XnStatus Remove(const XnChar* strName); + XnStatus Remove(ConstIterator where); + inline XnBool IsEmpty() const { return m_Hash.IsEmpty(); } + XnStatus Clear(); + + inline XnStatus Find(const XnChar* strName, Iterator& iter) { return m_Hash.Find(strName, iter); } + inline XnStatus Find(const XnChar* strName, ConstIterator& iter) const { return m_Hash.Find(strName, iter); } + inline XnStatus Get(const XnChar* strName, XnProperty*& pProp) const { return m_Hash.Get(strName, pProp); } + + inline Iterator begin() { return m_Hash.begin(); } + inline ConstIterator begin() const { return m_Hash.begin(); } + inline Iterator end() { return m_Hash.end(); } + inline ConstIterator end() const { return m_Hash.end(); } + + XnStatus CopyFrom(const XnActualPropertiesHash& other); + +protected: + XnPropertiesHash m_Hash; + XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; +}; + +#endif //__XN_ACTUAL_PROPERTIES_HASH_H__ diff --git a/Source/XnDDK/XnActualPropertyFactory.cpp b/Source/XnDDK/XnActualPropertyFactory.cpp index 5b41f9f..eb878ce 100644 --- a/Source/XnDDK/XnActualPropertyFactory.cpp +++ b/Source/XnDDK/XnActualPropertyFactory.cpp @@ -1,81 +1,81 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnActualPropertyFactory.h" -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnActualPropertyFactory::CreateProperty(XnPropertyType nType, const XnChar* strName, XnProperty** ppProperty, XnUInt32 nSize /* = 0 */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nType) - { - case XN_PROPERTY_TYPE_INTEGER: - XN_VALIDATE_NEW(*ppProperty, XnActualIntProperty, strName); - break; - case XN_PROPERTY_TYPE_REAL: - XN_VALIDATE_NEW(*ppProperty, XnActualRealProperty, strName); - break; - case XN_PROPERTY_TYPE_STRING: - XN_VALIDATE_NEW(*ppProperty, XnActualStringProperty, strName); - break; - case XN_PROPERTY_TYPE_GENERAL: - XnGeneralBuffer gbValue; - gbValue.pData = xnOSMalloc(nSize); - XN_VALIDATE_ALLOC_PTR(gbValue.pData); - gbValue.nDataSize = nSize; - XN_VALIDATE_NEW(*ppProperty, XnActualGeneralProperty, strName, gbValue); - break; - } - - return (XN_STATUS_OK); -} - -XnStatus XnActualPropertyFactory::FreeProperty(XnProperty* pProperty) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (pProperty->GetType() == XN_PROPERTY_TYPE_GENERAL) - { - XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProperty; - xnOSFree(pGenProp->GetValue().pData); - } - - XN_DELETE(pProperty); - - return (XN_STATUS_OK); +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnActualPropertyFactory.h" +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnActualPropertyFactory::CreateProperty(XnPropertyType nType, const XnChar* strName, XnProperty** ppProperty, XnUInt32 nSize /* = 0 */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nType) + { + case XN_PROPERTY_TYPE_INTEGER: + XN_VALIDATE_NEW(*ppProperty, XnActualIntProperty, strName); + break; + case XN_PROPERTY_TYPE_REAL: + XN_VALIDATE_NEW(*ppProperty, XnActualRealProperty, strName); + break; + case XN_PROPERTY_TYPE_STRING: + XN_VALIDATE_NEW(*ppProperty, XnActualStringProperty, strName); + break; + case XN_PROPERTY_TYPE_GENERAL: + XnGeneralBuffer gbValue; + gbValue.pData = xnOSMalloc(nSize); + XN_VALIDATE_ALLOC_PTR(gbValue.pData); + gbValue.nDataSize = nSize; + XN_VALIDATE_NEW(*ppProperty, XnActualGeneralProperty, strName, gbValue); + break; + } + + return (XN_STATUS_OK); +} + +XnStatus XnActualPropertyFactory::FreeProperty(XnProperty* pProperty) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (pProperty->GetType() == XN_PROPERTY_TYPE_GENERAL) + { + XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProperty; + xnOSFree(pGenProp->GetValue().pData); + } + + XN_DELETE(pProperty); + + return (XN_STATUS_OK); } \ No newline at end of file diff --git a/Source/XnDDK/XnActualPropertyFactory.h b/Source/XnDDK/XnActualPropertyFactory.h index 3f38514..9c292c7 100644 --- a/Source/XnDDK/XnActualPropertyFactory.h +++ b/Source/XnDDK/XnActualPropertyFactory.h @@ -1,45 +1,45 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_ACTUAL_PROPERTY_FACTORY_H__ -#define __XN_ACTUAL_PROPERTY_FACTORY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnActualPropertyFactory -{ -public: - static XnStatus CreateProperty(XnPropertyType nType, const XnChar* strName, XnProperty** ppProperty, XnUInt32 nSize = 0); - static XnStatus FreeProperty(XnProperty* pProperty); -}; - -#endif //__XN_ACTUAL_PROPERTY_FACTORY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_ACTUAL_PROPERTY_FACTORY_H__ +#define __XN_ACTUAL_PROPERTY_FACTORY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnActualPropertyFactory +{ +public: + static XnStatus CreateProperty(XnPropertyType nType, const XnChar* strName, XnProperty** ppProperty, XnUInt32 nSize = 0); + static XnStatus FreeProperty(XnProperty* pProperty); +}; + +#endif //__XN_ACTUAL_PROPERTY_FACTORY_H__ diff --git a/Source/XnDDK/XnActualRealProperty.cpp b/Source/XnDDK/XnActualRealProperty.cpp index 01417bc..2b95acf 100644 --- a/Source/XnDDK/XnActualRealProperty.cpp +++ b/Source/XnDDK/XnActualRealProperty.cpp @@ -1,53 +1,53 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnActualRealProperty.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnActualRealProperty::XnActualRealProperty(const XnChar* strName, XnDouble dInitialValue /* = 0.0 */, const XnChar* strModule /* = "" */) : - XnRealProperty(strName, &m_dValue, strModule), - m_dValue(dInitialValue) -{ - // set a callback for get operations - UpdateGetCallback(GetCallback, this); -} - -XnStatus XnActualRealProperty::SetCallback(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie) -{ - return pSender->UnsafeUpdateValue(dValue); -} - -XnStatus XN_CALLBACK_TYPE XnActualRealProperty::GetCallback(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie) -{ - *pdValue = pSender->GetValue(); - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnActualRealProperty.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnActualRealProperty::XnActualRealProperty(const XnChar* strName, XnDouble dInitialValue /* = 0.0 */, const XnChar* strModule /* = "" */) : + XnRealProperty(strName, &m_dValue, strModule), + m_dValue(dInitialValue) +{ + // set a callback for get operations + UpdateGetCallback(GetCallback, this); +} + +XnStatus XnActualRealProperty::SetCallback(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie) +{ + return pSender->UnsafeUpdateValue(dValue); +} + +XnStatus XN_CALLBACK_TYPE XnActualRealProperty::GetCallback(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie) +{ + *pdValue = pSender->GetValue(); + return XN_STATUS_OK; +} diff --git a/Source/XnDDK/XnActualRealProperty.h b/Source/XnDDK/XnActualRealProperty.h index a98a0ac..3a36a03 100644 --- a/Source/XnDDK/XnActualRealProperty.h +++ b/Source/XnDDK/XnActualRealProperty.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_ACTUAL_REAL_PROPERTY_H__ -#define __XN_ACTUAL_REAL_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type integer. -*/ -class XN_DDK_CPP_API XnActualRealProperty : public XnRealProperty -{ -public: - XnActualRealProperty(const XnChar* strName, XnDouble dInitialValue = 0.0, const XnChar* strModule = ""); - - inline XnDouble GetValue() const { return m_dValue; } - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie); - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnRealProperty::UpdateSetCallback((XnRealProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateSetCallbackToDefault() - { - UpdateSetCallback(SetCallback, this); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnRealProperty::UpdateGetCallback((XnRealProperty::GetFuncPtr)pFunc, pCookie); - } - -private: - static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie); - - XnDouble m_dValue; -}; - -#endif //__XN_ACTUAL_REAL_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_ACTUAL_REAL_PROPERTY_H__ +#define __XN_ACTUAL_REAL_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type integer. +*/ +class XN_DDK_CPP_API XnActualRealProperty : public XnRealProperty +{ +public: + XnActualRealProperty(const XnChar* strName, XnDouble dInitialValue = 0.0, const XnChar* strModule = ""); + + inline XnDouble GetValue() const { return m_dValue; } + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie); + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnRealProperty::UpdateSetCallback((XnRealProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateSetCallbackToDefault() + { + UpdateSetCallback(SetCallback, this); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnRealProperty::UpdateGetCallback((XnRealProperty::GetFuncPtr)pFunc, pCookie); + } + +private: + static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualRealProperty* pSender, XnDouble dValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualRealProperty* pSender, XnDouble* pdValue, void* pCookie); + + XnDouble m_dValue; +}; + +#endif //__XN_ACTUAL_REAL_PROPERTY_H__ diff --git a/Source/XnDDK/XnActualStringProperty.cpp b/Source/XnDDK/XnActualStringProperty.cpp index 8610ba6..45906d3 100644 --- a/Source/XnDDK/XnActualStringProperty.cpp +++ b/Source/XnDDK/XnActualStringProperty.cpp @@ -1,53 +1,53 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnActualStringProperty.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnActualStringProperty::XnActualStringProperty(const XnChar* strName, const XnChar* strInitialValue /* = "" */, const XnChar* strModule /* = "" */ ) : - XnStringProperty(strName, m_strValue, strModule) -{ - strncpy(m_strValue, strInitialValue, XN_DEVICE_MAX_STRING_LENGTH); - // set a callback for get operations - UpdateGetCallback(GetCallback, this); -} - -XnStatus XnActualStringProperty::SetCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie) -{ - return pSender->UnsafeUpdateValue(strValue); -} - -XnStatus XnActualStringProperty::GetCallback(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie) -{ - strncpy(csValue, pSender->GetValue(), XN_DEVICE_MAX_STRING_LENGTH); - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnActualStringProperty.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnActualStringProperty::XnActualStringProperty(const XnChar* strName, const XnChar* strInitialValue /* = "" */, const XnChar* strModule /* = "" */ ) : + XnStringProperty(strName, m_strValue, strModule) +{ + strncpy(m_strValue, strInitialValue, XN_DEVICE_MAX_STRING_LENGTH); + // set a callback for get operations + UpdateGetCallback(GetCallback, this); +} + +XnStatus XnActualStringProperty::SetCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie) +{ + return pSender->UnsafeUpdateValue(strValue); +} + +XnStatus XnActualStringProperty::GetCallback(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie) +{ + strncpy(csValue, pSender->GetValue(), XN_DEVICE_MAX_STRING_LENGTH); + return XN_STATUS_OK; +} diff --git a/Source/XnDDK/XnActualStringProperty.h b/Source/XnDDK/XnActualStringProperty.h index 2998ae0..9705d8f 100644 --- a/Source/XnDDK/XnActualStringProperty.h +++ b/Source/XnDDK/XnActualStringProperty.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_ACTUAL_STRING_PROPERTY_H__ -#define __XN_ACTUAL_STRING_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type general. -*/ -class XN_DDK_CPP_API XnActualStringProperty : public XnStringProperty -{ -public: - XnActualStringProperty(const XnChar* strName, const XnChar* strInitialValue = "", const XnChar* strModule = ""); - - inline const XnChar* GetValue() const { return m_strValue; } - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie); - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateSetCallbackToDefault() - { - UpdateSetCallback(SetCallback, this); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); - } - -private: - static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie); - - XnChar m_strValue[XN_DEVICE_MAX_STRING_LENGTH]; -}; - -#endif //__XN_ACTUAL_STRING_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_ACTUAL_STRING_PROPERTY_H__ +#define __XN_ACTUAL_STRING_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type general. +*/ +class XN_DDK_CPP_API XnActualStringProperty : public XnStringProperty +{ +public: + XnActualStringProperty(const XnChar* strName, const XnChar* strInitialValue = "", const XnChar* strModule = ""); + + inline const XnChar* GetValue() const { return m_strValue; } + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie); + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateSetCallbackToDefault() + { + UpdateSetCallback(SetCallback, this); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); + } + +private: + static XnStatus XN_CALLBACK_TYPE SetCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCallback(const XnActualStringProperty* pSender, XnChar* csValue, void* pCookie); + + XnChar m_strValue[XN_DEVICE_MAX_STRING_LENGTH]; +}; + +#endif //__XN_ACTUAL_STRING_PROPERTY_H__ diff --git a/Source/XnDDK/XnAudioStream.cpp b/Source/XnDDK/XnAudioStream.cpp index 33028dc..e066d30 100644 --- a/Source/XnDDK/XnAudioStream.cpp +++ b/Source/XnDDK/XnAudioStream.cpp @@ -1,112 +1,112 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnAudioStream.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_AUDIO_STREAM_BUFFER_SIZE_IN_SECONDS 1.5 - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnAudioStream::XnAudioStream(const XnChar* csName, XnUInt32 nMaxNumberOfChannels) : - XnStreamingStream(XN_STREAM_TYPE_AUDIO, csName), - m_SampleRate(XN_STREAM_PROPERTY_SAMPLE_RATE, XN_SAMPLE_RATE_48K), - m_NumberOfChannels(XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, 2), - m_nMaxNumberOfChannels(nMaxNumberOfChannels) -{ -} - -XnStatus XnAudioStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnStreamingStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - m_SampleRate.UpdateSetCallback(SetSampleRateCallback, this); - m_NumberOfChannels.UpdateSetCallback(SetNumberOfChannelsCallback, this); - - XN_VALIDATE_ADD_PROPERTIES(this, &m_SampleRate, &m_NumberOfChannels); - - // required size - nRetVal = RegisterRequiredSizeProperty(&m_SampleRate); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnAudioStream::SetSampleRate(XnSampleRate nSampleRate) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_SampleRate.UnsafeUpdateValue(nSampleRate); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnAudioStream::SetNumberOfChannels(XnUInt32 nNumberOfChannels) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_NumberOfChannels.UnsafeUpdateValue(nNumberOfChannels); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnAudioStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nSampleSize = 2 * m_nMaxNumberOfChannels; // 16-bit per channel (2 bytes) - XnUInt32 nSamples = (XnUInt32)(GetSampleRate() * XN_AUDIO_STREAM_BUFFER_SIZE_IN_SECONDS); - - *pnRequiredSize = nSamples * nSampleSize; - - return (XN_STATUS_OK); -} - -XnStatus XnAudioStream::SetSampleRateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnAudioStream* pStream = (XnAudioStream*)pCookie; - return pStream->SetSampleRate((XnSampleRate)nValue); -} - -XnStatus XnAudioStream::SetNumberOfChannelsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnAudioStream* pStream = (XnAudioStream*)pCookie; - return pStream->SetNumberOfChannels((XnUInt32)nValue); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnAudioStream.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_AUDIO_STREAM_BUFFER_SIZE_IN_SECONDS 1.5 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnAudioStream::XnAudioStream(const XnChar* csName, XnUInt32 nMaxNumberOfChannels) : + XnStreamingStream(XN_STREAM_TYPE_AUDIO, csName), + m_SampleRate(XN_STREAM_PROPERTY_SAMPLE_RATE, XN_SAMPLE_RATE_48K), + m_NumberOfChannels(XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, 2), + m_nMaxNumberOfChannels(nMaxNumberOfChannels) +{ +} + +XnStatus XnAudioStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnStreamingStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + m_SampleRate.UpdateSetCallback(SetSampleRateCallback, this); + m_NumberOfChannels.UpdateSetCallback(SetNumberOfChannelsCallback, this); + + XN_VALIDATE_ADD_PROPERTIES(this, &m_SampleRate, &m_NumberOfChannels); + + // required size + nRetVal = RegisterRequiredSizeProperty(&m_SampleRate); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnAudioStream::SetSampleRate(XnSampleRate nSampleRate) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_SampleRate.UnsafeUpdateValue(nSampleRate); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnAudioStream::SetNumberOfChannels(XnUInt32 nNumberOfChannels) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_NumberOfChannels.UnsafeUpdateValue(nNumberOfChannels); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnAudioStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nSampleSize = 2 * m_nMaxNumberOfChannels; // 16-bit per channel (2 bytes) + XnUInt32 nSamples = (XnUInt32)(GetSampleRate() * XN_AUDIO_STREAM_BUFFER_SIZE_IN_SECONDS); + + *pnRequiredSize = nSamples * nSampleSize; + + return (XN_STATUS_OK); +} + +XnStatus XnAudioStream::SetSampleRateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnAudioStream* pStream = (XnAudioStream*)pCookie; + return pStream->SetSampleRate((XnSampleRate)nValue); +} + +XnStatus XnAudioStream::SetNumberOfChannelsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnAudioStream* pStream = (XnAudioStream*)pCookie; + return pStream->SetNumberOfChannels((XnUInt32)nValue); +} diff --git a/Source/XnDDK/XnAudioStream.h b/Source/XnDDK/XnAudioStream.h index a9bb13e..0743e65 100644 --- a/Source/XnDDK/XnAudioStream.h +++ b/Source/XnDDK/XnAudioStream.h @@ -1,88 +1,88 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_AUDIO_STREAM_H__ -#define __XN_AUDIO_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -/** -* Represents a default base implementation of an audio stream. -*/ -class XN_DDK_CPP_API XnAudioStream : public XnStreamingStream -{ -public: - XnAudioStream(const XnChar* csName, XnUInt32 nMaxNumberOfChannels); - ~XnAudioStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnSampleRate GetSampleRate() const { return (XnSampleRate)m_SampleRate.GetValue(); } - inline XnUInt32 GetNumberOfChannels() const { return (XnUInt32)m_NumberOfChannels.GetValue(); } - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& SampleRateProperty() { return m_SampleRate; } - inline XnActualIntProperty& NumberOfChannelsProperty() { return m_NumberOfChannels; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetSampleRate(XnSampleRate nSampleRate); - virtual XnStatus SetNumberOfChannels(XnUInt32 nNumberOfChannels); - - XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; - -private: - - static XnStatus XN_CALLBACK_TYPE SetSampleRateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetNumberOfChannelsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_SampleRate; - XnActualIntProperty m_NumberOfChannels; - - XnUInt32 m_nMaxNumberOfChannels; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_AUDIO_STREAM_H__ +#define __XN_AUDIO_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +/** +* Represents a default base implementation of an audio stream. +*/ +class XN_DDK_CPP_API XnAudioStream : public XnStreamingStream +{ +public: + XnAudioStream(const XnChar* csName, XnUInt32 nMaxNumberOfChannels); + ~XnAudioStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnSampleRate GetSampleRate() const { return (XnSampleRate)m_SampleRate.GetValue(); } + inline XnUInt32 GetNumberOfChannels() const { return (XnUInt32)m_NumberOfChannels.GetValue(); } + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& SampleRateProperty() { return m_SampleRate; } + inline XnActualIntProperty& NumberOfChannelsProperty() { return m_NumberOfChannels; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetSampleRate(XnSampleRate nSampleRate); + virtual XnStatus SetNumberOfChannels(XnUInt32 nNumberOfChannels); + + XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; + +private: + + static XnStatus XN_CALLBACK_TYPE SetSampleRateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetNumberOfChannelsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_SampleRate; + XnActualIntProperty m_NumberOfChannels; + + XnUInt32 m_nMaxNumberOfChannels; +}; + #endif //__XN_AUDIO_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnBackwardsCompatibility36.cpp b/Source/XnDDK/XnBackwardsCompatibility36.cpp index b6fc095..59ab2c8 100644 --- a/Source/XnDDK/XnBackwardsCompatibility36.cpp +++ b/Source/XnDDK/XnBackwardsCompatibility36.cpp @@ -1,261 +1,261 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnBackwardsCompatibility36.h" -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnBCDepthFormatToOutputFormat(XnStreamDepthFormat nDepthFormat, XnOutputFormats* pnOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nDepthFormat) - { - case XN_DEPTH_FORMAT_RAW10: - case XN_DEPTH_FORMAT_RAW12: - *pnOutputFormat = XN_OUTPUT_FORMAT_DEPTH_VALUES; - break; - case XN_DEPTH_FORMAT_SHIFTS: - *pnOutputFormat = XN_OUTPUT_FORMAT_SHIFT_VALUES; - break; - default: - XN_LOG_ERROR_RETURN(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, XN_MASK_DDK, "Failed to translate depth format %d to output format!", nDepthFormat); - } - - return (XN_STATUS_OK); -} - -XnStatus XnBCOutputFormatToDepthFormat(XnOutputFormats nOutputFormat, XnStreamDepthFormat* pnDepthFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - *pnDepthFormat = XN_DEPTH_FORMAT_RAW12; - break; - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - *pnDepthFormat = XN_DEPTH_FORMAT_SHIFTS; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, XN_MASK_DDK, "Failed to translate output format %d to depth format!", nOutputFormat); - } - - return(XN_STATUS_OK); -} - -XnStatus XnBCImageFormatToOutputFormat(XnStreamImageFormat nImageFormat, XnOutputFormats* pnOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nImageFormat) - { - case XN_IMAGE_FORMAT_GRAYSCALE8: - *pnOutputFormat = XN_OUTPUT_FORMAT_GRAYSCALE8; - break; - case XN_IMAGE_FORMAT_RGB24: - *pnOutputFormat = XN_OUTPUT_FORMAT_RGB24; - break; - case XN_IMAGE_FORMAT_YUV422: - *pnOutputFormat = XN_OUTPUT_FORMAT_YUV422; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate image format %d to output format!", nImageFormat); - } - - return(XN_STATUS_OK); -} - -XnStatus XnBCOutputFormatToImageFormat(XnOutputFormats nOutputFormat, XnStreamImageFormat* pnImageFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - *pnImageFormat = XN_IMAGE_FORMAT_GRAYSCALE8; - break; - case XN_OUTPUT_FORMAT_RGB24: - *pnImageFormat = XN_IMAGE_FORMAT_RGB24; - break; - case XN_OUTPUT_FORMAT_YUV422: - *pnImageFormat = XN_IMAGE_FORMAT_YUV422; - break; - case XN_OUTPUT_FORMAT_GRAYSCALE16: - *pnImageFormat = (XnStreamImageFormat)-1; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate output format %d to image format!", nOutputFormat); - } - - return (XN_STATUS_OK); -} - -XnStatus XnBCAudioFormatToOutputFormat(XnStreamAudioFormat nAudioFormat, XnOutputFormats* pnOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nAudioFormat) - { - case XN_AUDIO_FORMAT_PCM: - *pnOutputFormat = XN_OUTPUT_FORMAT_PCM; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate audio format %d to output format!", nAudioFormat); - } - - return (XN_STATUS_OK); -} - -XnStatus XnBCOutputFormatToAudioFormat(XnOutputFormats nOutputFormat, XnStreamAudioFormat* pnAudioFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_PCM: - *pnAudioFormat = XN_AUDIO_FORMAT_PCM; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate audio format %d to output format!", nOutputFormat); - } - - return (XN_STATUS_OK); -} - -XnStreamDepthFormat XnBCGetStreamDepthFormatFromString(const XnChar* cpDepthFormat) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - if (cpDepthFormat == NULL) - { - return ((XnStreamDepthFormat)-1); - } - - // Convert each string into the proper depth format enum - if (strcmp(cpDepthFormat, "Raw12") == 0) - { - return (XN_DEPTH_FORMAT_RAW12); - } - else if (strcmp(cpDepthFormat, "Raw10") == 0) - { - return (XN_DEPTH_FORMAT_RAW10); - } - else if (strcmp(cpDepthFormat, "Shifts") == 0) - { - return (XN_DEPTH_FORMAT_SHIFTS); - } - else if (strcmp(cpDepthFormat, "Disabled") == 0) - { - return (XN_DEPTH_FORMAT_DISABLED); - } - - // Unknown mode... - return ((XnStreamDepthFormat)-1); -} - -XnStreamImageFormat XnBCGetStreamImageFormatFromString(const XnChar* cpImageFormat) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - if (cpImageFormat == NULL) - { - return ((XnStreamImageFormat)-1); - } - - // Convert each string into the proper image format enum - if (strcmp(cpImageFormat, "RGB24") == 0) - { - return (XN_IMAGE_FORMAT_RGB24); - } - else if (strcmp(cpImageFormat, "Gray8") == 0) - { - return (XN_IMAGE_FORMAT_GRAYSCALE8); - } - else if (strcmp(cpImageFormat, "YUV422") == 0) - { - return (XN_IMAGE_FORMAT_YUV422); - } - else if (strcmp(cpImageFormat, "Disabled") == 0) - { - return (XN_IMAGE_FORMAT_DISABLED); - } - - // Unknown mode... - return ((XnStreamImageFormat)-1); -} - -XnStreamAudioFormat XnBCGetStreamAudioFormatFromString(const XnChar* cpAudioFormat) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - if (cpAudioFormat == NULL) - { - return ((XnStreamAudioFormat)-1); - } - - // Convert each string into the proper image format enum - if (strcmp(cpAudioFormat, "PCM") == 0) - { - return (XN_AUDIO_FORMAT_PCM); - } - else if (strcmp(cpAudioFormat, "Disabled") == 0) - { - return (XN_AUDIO_FORMAT_DISABLED); - } - - // Unknown mode... - return ((XnStreamAudioFormat)-1); -} - -XN_STREAM_FLAGS_TYPE XnBCGetStreamFlagsFromString(XnChar* cpStreamFlags) -{ - // Local function variables - XnChar* cpToken = NULL; - XN_STREAM_FLAGS_TYPE StreamFlags = 0; - - cpToken = strtok (cpStreamFlags, ";"); - while (cpToken != NULL) - { - if (strcmp(cpToken, "Mirror") == 0) - { - StreamFlags |= XN_STREAM_FLAG_MIRROR; - } - else - { - return ((XN_STREAM_FLAGS_TYPE)-1); - } - - cpToken = strtok (NULL, ";"); - } - - // All is good... - return (StreamFlags); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnBackwardsCompatibility36.h" +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnBCDepthFormatToOutputFormat(XnStreamDepthFormat nDepthFormat, XnOutputFormats* pnOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nDepthFormat) + { + case XN_DEPTH_FORMAT_RAW10: + case XN_DEPTH_FORMAT_RAW12: + *pnOutputFormat = XN_OUTPUT_FORMAT_DEPTH_VALUES; + break; + case XN_DEPTH_FORMAT_SHIFTS: + *pnOutputFormat = XN_OUTPUT_FORMAT_SHIFT_VALUES; + break; + default: + XN_LOG_ERROR_RETURN(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, XN_MASK_DDK, "Failed to translate depth format %d to output format!", nDepthFormat); + } + + return (XN_STATUS_OK); +} + +XnStatus XnBCOutputFormatToDepthFormat(XnOutputFormats nOutputFormat, XnStreamDepthFormat* pnDepthFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + *pnDepthFormat = XN_DEPTH_FORMAT_RAW12; + break; + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + *pnDepthFormat = XN_DEPTH_FORMAT_SHIFTS; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT, XN_MASK_DDK, "Failed to translate output format %d to depth format!", nOutputFormat); + } + + return(XN_STATUS_OK); +} + +XnStatus XnBCImageFormatToOutputFormat(XnStreamImageFormat nImageFormat, XnOutputFormats* pnOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nImageFormat) + { + case XN_IMAGE_FORMAT_GRAYSCALE8: + *pnOutputFormat = XN_OUTPUT_FORMAT_GRAYSCALE8; + break; + case XN_IMAGE_FORMAT_RGB24: + *pnOutputFormat = XN_OUTPUT_FORMAT_RGB24; + break; + case XN_IMAGE_FORMAT_YUV422: + *pnOutputFormat = XN_OUTPUT_FORMAT_YUV422; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate image format %d to output format!", nImageFormat); + } + + return(XN_STATUS_OK); +} + +XnStatus XnBCOutputFormatToImageFormat(XnOutputFormats nOutputFormat, XnStreamImageFormat* pnImageFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + *pnImageFormat = XN_IMAGE_FORMAT_GRAYSCALE8; + break; + case XN_OUTPUT_FORMAT_RGB24: + *pnImageFormat = XN_IMAGE_FORMAT_RGB24; + break; + case XN_OUTPUT_FORMAT_YUV422: + *pnImageFormat = XN_IMAGE_FORMAT_YUV422; + break; + case XN_OUTPUT_FORMAT_GRAYSCALE16: + *pnImageFormat = (XnStreamImageFormat)-1; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate output format %d to image format!", nOutputFormat); + } + + return (XN_STATUS_OK); +} + +XnStatus XnBCAudioFormatToOutputFormat(XnStreamAudioFormat nAudioFormat, XnOutputFormats* pnOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nAudioFormat) + { + case XN_AUDIO_FORMAT_PCM: + *pnOutputFormat = XN_OUTPUT_FORMAT_PCM; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate audio format %d to output format!", nAudioFormat); + } + + return (XN_STATUS_OK); +} + +XnStatus XnBCOutputFormatToAudioFormat(XnOutputFormats nOutputFormat, XnStreamAudioFormat* pnAudioFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_PCM: + *pnAudioFormat = XN_AUDIO_FORMAT_PCM; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT, XN_MASK_DDK, "Failed to translate audio format %d to output format!", nOutputFormat); + } + + return (XN_STATUS_OK); +} + +XnStreamDepthFormat XnBCGetStreamDepthFormatFromString(const XnChar* cpDepthFormat) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + if (cpDepthFormat == NULL) + { + return ((XnStreamDepthFormat)-1); + } + + // Convert each string into the proper depth format enum + if (strcmp(cpDepthFormat, "Raw12") == 0) + { + return (XN_DEPTH_FORMAT_RAW12); + } + else if (strcmp(cpDepthFormat, "Raw10") == 0) + { + return (XN_DEPTH_FORMAT_RAW10); + } + else if (strcmp(cpDepthFormat, "Shifts") == 0) + { + return (XN_DEPTH_FORMAT_SHIFTS); + } + else if (strcmp(cpDepthFormat, "Disabled") == 0) + { + return (XN_DEPTH_FORMAT_DISABLED); + } + + // Unknown mode... + return ((XnStreamDepthFormat)-1); +} + +XnStreamImageFormat XnBCGetStreamImageFormatFromString(const XnChar* cpImageFormat) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + if (cpImageFormat == NULL) + { + return ((XnStreamImageFormat)-1); + } + + // Convert each string into the proper image format enum + if (strcmp(cpImageFormat, "RGB24") == 0) + { + return (XN_IMAGE_FORMAT_RGB24); + } + else if (strcmp(cpImageFormat, "Gray8") == 0) + { + return (XN_IMAGE_FORMAT_GRAYSCALE8); + } + else if (strcmp(cpImageFormat, "YUV422") == 0) + { + return (XN_IMAGE_FORMAT_YUV422); + } + else if (strcmp(cpImageFormat, "Disabled") == 0) + { + return (XN_IMAGE_FORMAT_DISABLED); + } + + // Unknown mode... + return ((XnStreamImageFormat)-1); +} + +XnStreamAudioFormat XnBCGetStreamAudioFormatFromString(const XnChar* cpAudioFormat) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + if (cpAudioFormat == NULL) + { + return ((XnStreamAudioFormat)-1); + } + + // Convert each string into the proper image format enum + if (strcmp(cpAudioFormat, "PCM") == 0) + { + return (XN_AUDIO_FORMAT_PCM); + } + else if (strcmp(cpAudioFormat, "Disabled") == 0) + { + return (XN_AUDIO_FORMAT_DISABLED); + } + + // Unknown mode... + return ((XnStreamAudioFormat)-1); +} + +XN_STREAM_FLAGS_TYPE XnBCGetStreamFlagsFromString(XnChar* cpStreamFlags) +{ + // Local function variables + XnChar* cpToken = NULL; + XN_STREAM_FLAGS_TYPE StreamFlags = 0; + + cpToken = strtok (cpStreamFlags, ";"); + while (cpToken != NULL) + { + if (strcmp(cpToken, "Mirror") == 0) + { + StreamFlags |= XN_STREAM_FLAG_MIRROR; + } + else + { + return ((XN_STREAM_FLAGS_TYPE)-1); + } + + cpToken = strtok (NULL, ";"); + } + + // All is good... + return (StreamFlags); +} diff --git a/Source/XnDDK/XnBackwardsCompatibility36.h b/Source/XnDDK/XnBackwardsCompatibility36.h index e48f096..428154f 100644 --- a/Source/XnDDK/XnBackwardsCompatibility36.h +++ b/Source/XnDDK/XnBackwardsCompatibility36.h @@ -1,52 +1,52 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_BACKWARDS_COMPATIBILITY36_H__ -#define __XN_BACKWARDS_COMPATIBILITY36_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#define _XN_IO_BC -#include - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnBCDepthFormatToOutputFormat(XnStreamDepthFormat nDepthFormat, XnOutputFormats* pnOutputFormat); -XN_DDK_API XnStatus XnBCOutputFormatToDepthFormat(XnOutputFormats nOutputFormat, XnStreamDepthFormat* pnDepthFormat); -XN_DDK_API XnStatus XnBCImageFormatToOutputFormat(XnStreamImageFormat nImageFormat, XnOutputFormats* pnOutputFormat); -XN_DDK_API XnStatus XnBCOutputFormatToImageFormat(XnOutputFormats nOutputFormat, XnStreamImageFormat* pnImageFormat); -XN_DDK_API XnStatus XnBCAudioFormatToOutputFormat(XnStreamAudioFormat nAudioFormat, XnOutputFormats* pnOutputFormat); -XN_DDK_API XnStatus XnBCOutputFormatToAudioFormat(XnOutputFormats nOutputFormat, XnStreamAudioFormat* pnAudioFormat); -XN_DDK_API XnStreamDepthFormat XnBCGetStreamDepthFormatFromString(const XnChar* cpDepthFormat); -XN_DDK_API XnStreamImageFormat XnBCGetStreamImageFormatFromString(const XnChar* cpImageFormat); -XN_DDK_API XnStreamAudioFormat XnBCGetStreamAudioFormatFromString(const XnChar* cpAudioFormat); -XN_DDK_API XN_STREAM_FLAGS_TYPE XnBCGetStreamFlagsFromString(XnChar* cpStreamFlags); - -#endif //__XN_BACKWARDS_COMPATIBILITY36_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_BACKWARDS_COMPATIBILITY36_H__ +#define __XN_BACKWARDS_COMPATIBILITY36_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#define _XN_IO_BC +#include + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnBCDepthFormatToOutputFormat(XnStreamDepthFormat nDepthFormat, XnOutputFormats* pnOutputFormat); +XN_DDK_API XnStatus XnBCOutputFormatToDepthFormat(XnOutputFormats nOutputFormat, XnStreamDepthFormat* pnDepthFormat); +XN_DDK_API XnStatus XnBCImageFormatToOutputFormat(XnStreamImageFormat nImageFormat, XnOutputFormats* pnOutputFormat); +XN_DDK_API XnStatus XnBCOutputFormatToImageFormat(XnOutputFormats nOutputFormat, XnStreamImageFormat* pnImageFormat); +XN_DDK_API XnStatus XnBCAudioFormatToOutputFormat(XnStreamAudioFormat nAudioFormat, XnOutputFormats* pnOutputFormat); +XN_DDK_API XnStatus XnBCOutputFormatToAudioFormat(XnOutputFormats nOutputFormat, XnStreamAudioFormat* pnAudioFormat); +XN_DDK_API XnStreamDepthFormat XnBCGetStreamDepthFormatFromString(const XnChar* cpDepthFormat); +XN_DDK_API XnStreamImageFormat XnBCGetStreamImageFormatFromString(const XnChar* cpImageFormat); +XN_DDK_API XnStreamAudioFormat XnBCGetStreamAudioFormatFromString(const XnChar* cpAudioFormat); +XN_DDK_API XN_STREAM_FLAGS_TYPE XnBCGetStreamFlagsFromString(XnChar* cpStreamFlags); + +#endif //__XN_BACKWARDS_COMPATIBILITY36_H__ diff --git a/Source/XnDDK/XnBufferPool.cpp b/Source/XnDDK/XnBufferPool.cpp index 20bad25..7a797d3 100644 --- a/Source/XnDDK/XnBufferPool.cpp +++ b/Source/XnDDK/XnBufferPool.cpp @@ -1,215 +1,215 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnBufferPool.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnBufferPool::XnBufferPool(XnUInt32 nBufferCount) : - m_nBufferCount(nBufferCount), - m_nBufferSize(0), - m_hLock(NULL), - m_dump(XN_DUMP_CLOSED) -{} - -XnBufferPool::~XnBufferPool() -{ - XnBufferPool::Free(); -} - -XnStatus XnBufferPool::Init(XnUInt32 nBufferSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnDumpInit(&m_dump, "BufferPool", "", "bufferpool_%x.txt", this); - - nRetVal = xnOSCreateCriticalSection(&m_hLock); - XN_IS_STATUS_OK(nRetVal); - - // allocate buffers - nRetVal = ChangeBufferSize(nBufferSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnBufferPool::Free() -{ - if (m_hLock != NULL) - { - xnOSCloseCriticalSection(&m_hLock); - m_hLock = NULL; - } -} - -XnStatus XnBufferPool::ChangeBufferSize(XnUInt32 nBufferSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnDumpWriteString(m_dump, "changing buffer size to %d\n", nBufferSize); - - xnOSEnterCriticalSection(&m_hLock); - - m_nBufferSize = nBufferSize; - - nRetVal = AllocateBuffers(); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(&m_hLock); - return (nRetVal); - } - - xnOSLeaveCriticalSection(&m_hLock); - - return (XN_STATUS_OK); -} - -void XnBufferPool::FreeAll(XnBool bForceDestroyOfLockedBuffers) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // free existing buffers - XnBuffersList::Iterator it = m_AllBuffers.begin(); - while (it != m_AllBuffers.end()) - { - XnBuffersList::Iterator currIt = it; - - // first advance (we might remove this item) - ++it; - - // now check current - XnBufferInPool* pBuffer = *currIt; - - // check if item is in free list (or we're forcing deletion) - if (bForceDestroyOfLockedBuffers || pBuffer->m_nRefCount == 0) - { - DestroyBuffer(pBuffer); - m_AllBuffers.Remove(currIt); - } - else - { - // we can't free it, cause it's still locked. instead, mark it for deletion - pBuffer->m_bDestroy = TRUE; - } - } - - m_FreeBuffers.Clear(); -} - -XnStatus XnBufferPool::GetBuffer(XnBuffer** ppBuffer) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnOSEnterCriticalSection(&m_hLock); - - XnBuffersList::Iterator it = m_FreeBuffers.begin(); - if (it == m_FreeBuffers.end()) - { - xnOSLeaveCriticalSection(&m_hLock); - return XN_STATUS_ALLOC_FAILED; - } - - XnBufferInPool* pBuffer = *it; - - // remove from list - nRetVal = m_FreeBuffers.Remove(it); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(&m_hLock); - return XN_STATUS_ALLOC_FAILED; - } - - pBuffer->m_nRefCount = 1; - xnDumpWriteString(m_dump, "%u taken from pool\n", pBuffer->m_nID); - - xnOSLeaveCriticalSection(&m_hLock); - - *ppBuffer = pBuffer; - - return (XN_STATUS_OK); -} - -void XnBufferPool::AddRef(XnBuffer* pBuffer) -{ - if (pBuffer == NULL) - { - return; - } - - xnOSEnterCriticalSection(&m_hLock); - XnBufferInPool* pBufferInPool = (XnBufferInPool*)pBuffer; - ++pBufferInPool->m_nRefCount; - - xnDumpWriteString(m_dump, "%u add ref (%d)\n", pBufferInPool->m_nID, pBufferInPool->m_nRefCount); - - xnOSLeaveCriticalSection(&m_hLock); -} - -void XnBufferPool::DecRef(XnBuffer* pBuffer) -{ - if (pBuffer == NULL) - { - return; - } - - XnBufferInPool* pBufInPool = (XnBufferInPool*)pBuffer; - - xnOSEnterCriticalSection(&m_hLock); - - xnDumpWriteString(m_dump, "%u dec ref (%d)", pBufInPool->m_nID, pBufInPool->m_nRefCount-1); - - if (--pBufInPool->m_nRefCount == 0) - { - if (pBufInPool->m_bDestroy) - { - // remove it from all buffers pool - XnBuffersList::ConstIterator it = m_AllBuffers.Find(pBufInPool); - XN_ASSERT(it != m_AllBuffers.end()); - m_AllBuffers.Remove(it); - // and free it - DestroyBuffer(pBufInPool); - xnDumpWriteString(m_dump, "destroy!\n"); - } - else - { - // return it to free buffers list - m_FreeBuffers.AddLast(pBufInPool); - xnDumpWriteString(m_dump, "return to pool!\n"); - } - } - else - { - xnDumpWriteString(m_dump, "\n"); - } - - xnOSLeaveCriticalSection(&m_hLock); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnBufferPool.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnBufferPool::XnBufferPool(XnUInt32 nBufferCount) : + m_nBufferCount(nBufferCount), + m_nBufferSize(0), + m_hLock(NULL), + m_dump(XN_DUMP_CLOSED) +{} + +XnBufferPool::~XnBufferPool() +{ + XnBufferPool::Free(); +} + +XnStatus XnBufferPool::Init(XnUInt32 nBufferSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnDumpInit(&m_dump, "BufferPool", "", "bufferpool_%x.txt", this); + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + // allocate buffers + nRetVal = ChangeBufferSize(nBufferSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnBufferPool::Free() +{ + if (m_hLock != NULL) + { + xnOSCloseCriticalSection(&m_hLock); + m_hLock = NULL; + } +} + +XnStatus XnBufferPool::ChangeBufferSize(XnUInt32 nBufferSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnDumpWriteString(m_dump, "changing buffer size to %d\n", nBufferSize); + + xnOSEnterCriticalSection(&m_hLock); + + m_nBufferSize = nBufferSize; + + nRetVal = AllocateBuffers(); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(&m_hLock); + return (nRetVal); + } + + xnOSLeaveCriticalSection(&m_hLock); + + return (XN_STATUS_OK); +} + +void XnBufferPool::FreeAll(XnBool bForceDestroyOfLockedBuffers) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // free existing buffers + XnBuffersList::Iterator it = m_AllBuffers.begin(); + while (it != m_AllBuffers.end()) + { + XnBuffersList::Iterator currIt = it; + + // first advance (we might remove this item) + ++it; + + // now check current + XnBufferInPool* pBuffer = *currIt; + + // check if item is in free list (or we're forcing deletion) + if (bForceDestroyOfLockedBuffers || pBuffer->m_nRefCount == 0) + { + DestroyBuffer(pBuffer); + m_AllBuffers.Remove(currIt); + } + else + { + // we can't free it, cause it's still locked. instead, mark it for deletion + pBuffer->m_bDestroy = TRUE; + } + } + + m_FreeBuffers.Clear(); +} + +XnStatus XnBufferPool::GetBuffer(XnBuffer** ppBuffer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnOSEnterCriticalSection(&m_hLock); + + XnBuffersList::Iterator it = m_FreeBuffers.begin(); + if (it == m_FreeBuffers.end()) + { + xnOSLeaveCriticalSection(&m_hLock); + return XN_STATUS_ALLOC_FAILED; + } + + XnBufferInPool* pBuffer = *it; + + // remove from list + nRetVal = m_FreeBuffers.Remove(it); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(&m_hLock); + return XN_STATUS_ALLOC_FAILED; + } + + pBuffer->m_nRefCount = 1; + xnDumpWriteString(m_dump, "%u taken from pool\n", pBuffer->m_nID); + + xnOSLeaveCriticalSection(&m_hLock); + + *ppBuffer = pBuffer; + + return (XN_STATUS_OK); +} + +void XnBufferPool::AddRef(XnBuffer* pBuffer) +{ + if (pBuffer == NULL) + { + return; + } + + xnOSEnterCriticalSection(&m_hLock); + XnBufferInPool* pBufferInPool = (XnBufferInPool*)pBuffer; + ++pBufferInPool->m_nRefCount; + + xnDumpWriteString(m_dump, "%u add ref (%d)\n", pBufferInPool->m_nID, pBufferInPool->m_nRefCount); + + xnOSLeaveCriticalSection(&m_hLock); +} + +void XnBufferPool::DecRef(XnBuffer* pBuffer) +{ + if (pBuffer == NULL) + { + return; + } + + XnBufferInPool* pBufInPool = (XnBufferInPool*)pBuffer; + + xnOSEnterCriticalSection(&m_hLock); + + xnDumpWriteString(m_dump, "%u dec ref (%d)", pBufInPool->m_nID, pBufInPool->m_nRefCount-1); + + if (--pBufInPool->m_nRefCount == 0) + { + if (pBufInPool->m_bDestroy) + { + // remove it from all buffers pool + XnBuffersList::ConstIterator it = m_AllBuffers.Find(pBufInPool); + XN_ASSERT(it != m_AllBuffers.end()); + m_AllBuffers.Remove(it); + // and free it + DestroyBuffer(pBufInPool); + xnDumpWriteString(m_dump, "destroy!\n"); + } + else + { + // return it to free buffers list + m_FreeBuffers.AddLast(pBufInPool); + xnDumpWriteString(m_dump, "return to pool!\n"); + } + } + else + { + xnDumpWriteString(m_dump, "\n"); + } + + xnOSLeaveCriticalSection(&m_hLock); +} diff --git a/Source/XnDDK/XnBufferPool.h b/Source/XnDDK/XnBufferPool.h index d6a3c1a..fa00a14 100644 --- a/Source/XnDDK/XnBufferPool.h +++ b/Source/XnDDK/XnBufferPool.h @@ -1,95 +1,95 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_BUFFER_POOL_H__ -#define __XN_BUFFER_POOL_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnBufferInPool : public XnBuffer -{ -public: - XnBufferInPool() : m_nRefCount(0), m_bDestroy(FALSE) {} - ~XnBufferInPool() {} - - XnUInt32 m_nID; -private: - friend class XnBufferPool; - - XnUInt32 m_nRefCount; - XnBool m_bDestroy; -}; - -class XN_DDK_CPP_API XnBufferPool -{ -public: - XnBufferPool(XnUInt32 nBufferCount); - virtual ~XnBufferPool(); - - XnStatus Init(XnUInt32 nBufferSize); - virtual void Free(); - - XnStatus ChangeBufferSize(XnUInt32 nBufferSize); - - XnStatus GetBuffer(XnBuffer** ppBuffer); - - void AddRef(XnBuffer* pBuffer); - - void DecRef(XnBuffer* pBuffer); - - inline void Lock() { xnOSEnterCriticalSection(&m_hLock); } - inline void Unlock() { xnOSLeaveCriticalSection(&m_hLock); } - - inline XnDump& Dump() { return m_dump; } - -protected: - XN_DECLARE_LIST(XnBufferInPool*, XnBuffersList); - - void FreeAll(XnBool bForceDestroyOfLockedBuffers); - - virtual XnStatus AllocateBuffers() = 0; - virtual void DestroyBuffer(XnBufferInPool* pBuffer) = 0; - -protected: - XnUInt32 m_nBufferSize; - XnUInt32 m_nBufferCount; - XnBuffersList m_AllBuffers; - XnBuffersList m_FreeBuffers; // a list of available buffers - XN_CRITICAL_SECTION_HANDLE m_hLock; - XnDump m_dump; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_BUFFER_POOL_H__ +#define __XN_BUFFER_POOL_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnBufferInPool : public XnBuffer +{ +public: + XnBufferInPool() : m_nRefCount(0), m_bDestroy(FALSE) {} + ~XnBufferInPool() {} + + XnUInt32 m_nID; +private: + friend class XnBufferPool; + + XnUInt32 m_nRefCount; + XnBool m_bDestroy; +}; + +class XN_DDK_CPP_API XnBufferPool +{ +public: + XnBufferPool(XnUInt32 nBufferCount); + virtual ~XnBufferPool(); + + XnStatus Init(XnUInt32 nBufferSize); + virtual void Free(); + + XnStatus ChangeBufferSize(XnUInt32 nBufferSize); + + XnStatus GetBuffer(XnBuffer** ppBuffer); + + void AddRef(XnBuffer* pBuffer); + + void DecRef(XnBuffer* pBuffer); + + inline void Lock() { xnOSEnterCriticalSection(&m_hLock); } + inline void Unlock() { xnOSLeaveCriticalSection(&m_hLock); } + + inline XnDump& Dump() { return m_dump; } + +protected: + XN_DECLARE_LIST(XnBufferInPool*, XnBuffersList); + + void FreeAll(XnBool bForceDestroyOfLockedBuffers); + + virtual XnStatus AllocateBuffers() = 0; + virtual void DestroyBuffer(XnBufferInPool* pBuffer) = 0; + +protected: + XnUInt32 m_nBufferSize; + XnUInt32 m_nBufferCount; + XnBuffersList m_AllBuffers; + XnBuffersList m_FreeBuffers; // a list of available buffers + XN_CRITICAL_SECTION_HANDLE m_hLock; + XnDump m_dump; +}; + #endif // __XN_BUFFER_POOL_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnCodecFactory.cpp b/Source/XnDDK/XnCodecFactory.cpp index d65d649..2b52281 100644 --- a/Source/XnDDK/XnCodecFactory.cpp +++ b/Source/XnDDK/XnCodecFactory.cpp @@ -1,120 +1,120 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecFactory.h" -#include "XnIntProperty.h" -#include -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnCodecFactory::Create(XnCompressionFormats nFormat, XnDeviceModule* pStream, const XnChar* StreamName, XnCodec** ppCodec) -{ - XnStatus nRetVal = XN_STATUS_OK; - XnCodec* pCodec = NULL; - - switch (nFormat) - { - case XN_COMPRESSION_NONE: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, XnUncompressedCodec); - } - break; - case XN_COMPRESSION_16Z: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zCodec); - } - break; - case XN_COMPRESSION_16Z_EMB_TABLE: - { - // first we need to find max depth - XnUInt64 nMaxDepth; - - nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_MAX_DEPTH, &nMaxDepth); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zEmbTablesCodec, (XnDepthPixel)nMaxDepth); - } - break; - case XN_COMPRESSION_COLOR_8Z: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn8zCodec); - } - break; - case XN_COMPRESSION_JPEG: - { - // check what is the output format - XnUInt64 nOutputFormat; - nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, &nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - XnBool bRGB = FALSE; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - bRGB = FALSE; - break; - case XN_OUTPUT_FORMAT_RGB24: - bRGB = TRUE; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory currently supports JPEG codec only for streams of type Gray8 or RGB24!"); - } - - // take X and Y res - XnUInt64 nXRes, nYRes; - nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_X_RES, &nXRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_Y_RES, &nYRes); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW_AND_INIT(pCodec, XnJpegCodec, bRGB, (XnUInt32)nXRes, (XnUInt32)nYRes); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory does not support compression type %d", nFormat); - } - - *ppCodec = pCodec; - return (XN_STATUS_OK); -} - -void XnCodecFactory::Destroy(XnCodec* pCodec) -{ - XN_DELETE(pCodec); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecFactory.h" +#include "XnIntProperty.h" +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnCodecFactory::Create(XnCompressionFormats nFormat, XnDeviceModule* pStream, const XnChar* StreamName, XnCodec** ppCodec) +{ + XnStatus nRetVal = XN_STATUS_OK; + XnCodec* pCodec = NULL; + + switch (nFormat) + { + case XN_COMPRESSION_NONE: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, XnUncompressedCodec); + } + break; + case XN_COMPRESSION_16Z: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zCodec); + } + break; + case XN_COMPRESSION_16Z_EMB_TABLE: + { + // first we need to find max depth + XnUInt64 nMaxDepth; + + nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_MAX_DEPTH, &nMaxDepth); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zEmbTablesCodec, (XnDepthPixel)nMaxDepth); + } + break; + case XN_COMPRESSION_COLOR_8Z: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn8zCodec); + } + break; + case XN_COMPRESSION_JPEG: + { + // check what is the output format + XnUInt64 nOutputFormat; + nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, &nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + XnBool bRGB = FALSE; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + bRGB = FALSE; + break; + case XN_OUTPUT_FORMAT_RGB24: + bRGB = TRUE; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory currently supports JPEG codec only for streams of type Gray8 or RGB24!"); + } + + // take X and Y res + XnUInt64 nXRes, nYRes; + nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_X_RES, &nXRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pStream->GetProperty(XN_STREAM_PROPERTY_Y_RES, &nYRes); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_NEW_AND_INIT(pCodec, XnJpegCodec, bRGB, (XnUInt32)nXRes, (XnUInt32)nYRes); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory does not support compression type %d", nFormat); + } + + *ppCodec = pCodec; + return (XN_STATUS_OK); +} + +void XnCodecFactory::Destroy(XnCodec* pCodec) +{ + XN_DELETE(pCodec); +} + diff --git a/Source/XnDDK/XnCodecFactory.h b/Source/XnDDK/XnCodecFactory.h index 65c460d..2c98892 100644 --- a/Source/XnDDK/XnCodecFactory.h +++ b/Source/XnDDK/XnCodecFactory.h @@ -1,49 +1,49 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_CODEC_FACTORY_H__ -#define __XN_CODEC_FACTORY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnCodecFactory -{ -public: - static XnStatus Create(XnCompressionFormats nFormat, XnDeviceModule* pStream, const XnChar* StreamName, XnCodec** ppCodec); - static void Destroy(XnCodec* pCodec); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_CODEC_FACTORY_H__ +#define __XN_CODEC_FACTORY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnCodecFactory +{ +public: + static XnStatus Create(XnCompressionFormats nFormat, XnDeviceModule* pStream, const XnChar* StreamName, XnCodec** ppCodec); + static void Destroy(XnCodec* pCodec); +}; + #endif //__XN_CODEC_FACTORY_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDDK.cpp b/Source/XnDDK/XnDDK.cpp index 1c2c67a..c7e152e 100644 --- a/Source/XnDDK/XnDDK.cpp +++ b/Source/XnDDK/XnDDK.cpp @@ -1,144 +1,144 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include "XnDeviceManager.h" - -// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! -XN_API_EXPORT_INIT() - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -static XnBool g_XnDDKWasInit = FALSE; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnDDKInit(const XnChar* strDevicesDir) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Was the DDK subsystem already initialized? - if (g_XnDDKWasInit == FALSE) - { - // Init the Formats library - nRetVal = XnFormatsInit(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) - return nRetVal; - - // Init DeviceManager - nRetVal = XnDeviceManagerInit(strDevicesDir); - XN_IS_STATUS_OK(nRetVal); - - g_XnDDKWasInit = TRUE; - } - else - { - // Trying to init twice... - return (XN_STATUS_DDK_ALREADY_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDDKInitFromINIFile(const XnChar* cpINIFileName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(cpINIFileName); - - // Was the DDK subsystem already initialized? - if (g_XnDDKWasInit == FALSE) - { - // Init the Formats library - nRetVal = XnFormatsInitFromINIFile(cpINIFileName); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) - return nRetVal; - - // read devices directory - XnChar strDevicesDirectory[XN_INI_MAX_LEN] = ""; - XnChar* pDir = NULL; - if (XN_STATUS_OK == xnOSReadStringFromINI(cpINIFileName, "DDK", "DevicesDir", strDevicesDirectory, XN_INI_MAX_LEN)) - { - XN_VALIDATE_STR_APPEND(strDevicesDirectory, XN_FILE_DIR_SEP, XN_INI_MAX_LEN, nRetVal); - pDir = strDevicesDirectory; - } - - // Init DeviceManager - nRetVal = XnDeviceManagerInit(pDir); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) - return nRetVal; - - g_XnDDKWasInit = TRUE; - } - else - { - // Trying to init twice... - return (XN_STATUS_DDK_ALREADY_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDDKShutdown() -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - - // Was the DDK subsystem initialized? - if (g_XnDDKWasInit == TRUE) - { - // shutdown device manager - nRetVal = XnDeviceManagerShutdown(); - XN_IS_STATUS_OK(nRetVal); - - // shutdown the Formats library - nRetVal = XnFormatsShutdown(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_FORMATS_NOT_INIT) - return nRetVal; - - g_XnDDKWasInit = FALSE; - } - else - { - // Trying to shutdown without doing init... - return (XN_STATUS_DDK_NOT_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include "XnDeviceManager.h" + +// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! +XN_API_EXPORT_INIT() + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +static XnBool g_XnDDKWasInit = FALSE; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnDDKInit(const XnChar* strDevicesDir) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Was the DDK subsystem already initialized? + if (g_XnDDKWasInit == FALSE) + { + // Init the Formats library + nRetVal = XnFormatsInit(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) + return nRetVal; + + // Init DeviceManager + nRetVal = XnDeviceManagerInit(strDevicesDir); + XN_IS_STATUS_OK(nRetVal); + + g_XnDDKWasInit = TRUE; + } + else + { + // Trying to init twice... + return (XN_STATUS_DDK_ALREADY_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDDKInitFromINIFile(const XnChar* cpINIFileName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(cpINIFileName); + + // Was the DDK subsystem already initialized? + if (g_XnDDKWasInit == FALSE) + { + // Init the Formats library + nRetVal = XnFormatsInitFromINIFile(cpINIFileName); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) + return nRetVal; + + // read devices directory + XnChar strDevicesDirectory[XN_INI_MAX_LEN] = ""; + XnChar* pDir = NULL; + if (XN_STATUS_OK == xnOSReadStringFromINI(cpINIFileName, "DDK", "DevicesDir", strDevicesDirectory, XN_INI_MAX_LEN)) + { + XN_VALIDATE_STR_APPEND(strDevicesDirectory, XN_FILE_DIR_SEP, XN_INI_MAX_LEN, nRetVal); + pDir = strDevicesDirectory; + } + + // Init DeviceManager + nRetVal = XnDeviceManagerInit(pDir); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) + return nRetVal; + + g_XnDDKWasInit = TRUE; + } + else + { + // Trying to init twice... + return (XN_STATUS_DDK_ALREADY_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDDKShutdown() +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + + // Was the DDK subsystem initialized? + if (g_XnDDKWasInit == TRUE) + { + // shutdown device manager + nRetVal = XnDeviceManagerShutdown(); + XN_IS_STATUS_OK(nRetVal); + + // shutdown the Formats library + nRetVal = XnFormatsShutdown(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_FORMATS_NOT_INIT) + return nRetVal; + + g_XnDDKWasInit = FALSE; + } + else + { + // Trying to shutdown without doing init... + return (XN_STATUS_DDK_NOT_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnDDKStatus.cpp b/Source/XnDDK/XnDDKStatus.cpp index 07858c0..e32f5f3 100644 --- a/Source/XnDDK/XnDDKStatus.cpp +++ b/Source/XnDDK/XnDDKStatus.cpp @@ -1,33 +1,33 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -// registration is done by including XnStatusRegister *before* including the list of errors -#include -#include +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +// registration is done by including XnStatusRegister *before* including the list of errors +#include +#include diff --git a/Source/XnDDK/XnDataPacker.cpp b/Source/XnDDK/XnDataPacker.cpp index 1230dfd..3ee1efb 100644 --- a/Source/XnDDK/XnDataPacker.cpp +++ b/Source/XnDDK/XnDataPacker.cpp @@ -1,1113 +1,1113 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataPacker.h" -#include -#include -#include -#include "XnStreamDataInternal.h" -#include "XnPropertySetInternal.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_PACKED_STRING 1000 -#define XN_PACKED_PROPERTY_SET_MODULES_END_MARKER 1001 -#define XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER 1002 - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -#pragma pack (push, 1) - -typedef struct XnPackedDataHeader -{ - XnPackedDataType nType; - XnUInt32 nSize; -} XnPackedDataHeader; - -#pragma pack (pop) - -//--------------------------------------------------------------------------- -// Macros -//--------------------------------------------------------------------------- -#define XN_VALIDATE_OBJECT_TYPE(type) \ - if (m_pCurrentHeader == NULL) \ - { \ - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Cannot read an object before a call to ReadNextObject()!"); \ - } \ - if (m_pCurrentHeader->nType != type) \ - { \ - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Trying to read object of type %d when stream contains object of type %d!", type, m_pCurrentHeader->nType); \ - } - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDataPacker::XnDataPacker(XnIOStream* pStream, XnUInt32 nInternalBufferSize) : - m_pStream(pStream), - m_nBufferSize(nInternalBufferSize), - m_nInternalBufferReadIndex(0), - m_pCurrentHeader(NULL) -{ - ResetReadBuffer(); -} - -XnDataPacker::~XnDataPacker() -{ - Free(); -} - -XnStatus XnDataPacker::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // we allocate enough space for the data and the header - nRetVal = m_InternalBuffer.Allocate(m_nBufferSize + sizeof(XnPackedDataHeader)); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::Free() -{ - m_InternalBuffer.Free(); - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteNewStream(const XnChar* strType, const XnChar* strName, const XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_NEW_STREAM); - - nRetVal = WriteStringToBuffer(strType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(strName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WritePropertySetImpl(pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadNewStreamName(XnChar* csType, XnChar* csName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_NEW_STREAM); - - // keep last read index (because we only want to know the stream name, without - // actually removing anything from the buffer - XnUInt32 nReadIndexBefore = m_nInternalBufferReadIndex; - - // read stream type - nRetVal = ReadStringFromBuffer(csType); - XN_IS_STATUS_OK(nRetVal); - - // read stream name - nRetVal = ReadStringFromBuffer(csName); - XN_IS_STATUS_OK(nRetVal); - - // restore read index - m_nInternalBufferReadIndex = nReadIndexBefore; - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadNewStream(XnChar* csType, XnChar* csName, XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_NEW_STREAM); - - nRetVal = ReadStringFromBuffer(csType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(csName); - XN_IS_STATUS_OK(nRetVal); - - MoveToNextObject(); - - nRetVal = ReadPropertySetImpl(pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertySetProperties(const XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnPropertySetData::Iterator it = pSet->pData->begin(); it != pSet->pData->end(); ++it) - { - XnActualPropertiesHash* pModule = it.Value(); - for (XnActualPropertiesHash::ConstIterator itProp = pModule->begin(); itProp != pModule->end(); ++itProp) - { - switch (itProp.Value()->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pProp = (XnActualIntProperty*)itProp.Value(); - nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pProp = (XnActualRealProperty*)itProp.Value(); - nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pProp = (XnActualStringProperty*)itProp.Value(); - nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)itProp.Value(); - nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d", itProp.Value()->GetType()); - } - } - } - - StartWritingIntenalObject(XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER); - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertySetImpl(const XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_PROPERTY_SET); - - // Write module names - for (XnPropertySetData::Iterator it = pPropertySet->pData->begin(); it != pPropertySet->pData->end(); ++it) - { - nRetVal = WriteString(it.Key()); - XN_IS_STATUS_OK(nRetVal); - } - - StartWritingIntenalObject(XN_PACKED_PROPERTY_SET_MODULES_END_MARKER); - EndWritingInternalObject(); - - // write properties - nRetVal = WritePropertySetProperties(pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertySet(const XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = WritePropertySetImpl(pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertySetImpl(XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_PROPERTY_SET); - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - - // read property set marker - MoveToNextObject(); - - while (m_pCurrentHeader->nType != XN_PACKED_PROPERTY_SET_MODULES_END_MARKER) - { - nRetVal = ReadString(strModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddModule(pPropertySet, strModule); - XN_IS_STATUS_OK(nRetVal); - } - - // read properties - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - - // read the modules end marker - MoveToNextObject(); - - while (m_pCurrentHeader->nType != XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER) - { - // read property and add it to set - switch (m_pCurrentHeader->nType) - { - case XN_PACKED_INT_PROPERTY: - { - XnUInt64 nValue; - nRetVal = ReadPropertyImpl(strModule, strName, &nValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pPropertySet, strModule, strName, nValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_REAL_PROPERTY: - { - XnDouble dValue; - nRetVal = ReadPropertyImpl(strModule, strName, &dValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddRealProperty(pPropertySet, strModule, strName, dValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_STRING_PROPERTY: - { - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = ReadPropertyImpl(strModule, strName, strValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddStringProperty(pPropertySet, strModule, strName, strValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_GENERAL_PROPERTY: - { - XnGeneralBuffer gbValue; - nRetVal = ReadPropertyImpl(strModule, strName, &gbValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddGeneralProperty(pPropertySet, strModule, strName, &gbValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Stream contains an object of type %d in the middle of a property set!", m_pCurrentHeader->nType); - } - } // props loop - - // read properties end marker - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertySet(XnPropertySet* pPropertySet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReadPropertySetImpl(pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteStreamRemoved(const XnChar* csStreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_STREAM_REMOVED); - - nRetVal = WriteStringToBuffer(csStreamName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadStreamRemoved(XnChar* csStreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_REMOVED); - - nRetVal = ReadStringFromBuffer(csStreamName); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_INT_PROPERTY); - - nRetVal = WriteStringToBuffer(csModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(csProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_InternalBuffer.Write((const XnUChar*)&nValue, sizeof(XnUInt64)); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = WritePropertyImpl(csModule, csProp, nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_INT_PROPERTY); - - nRetVal = ReadStringFromBuffer(pcsModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(pcsProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadInternalBuffer((XnUChar*)pnValue, sizeof(XnUInt64)); - XN_IS_STATUS_OK(nRetVal); - - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pnValue); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_REAL_PROPERTY); - - nRetVal = WriteStringToBuffer(csModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(csProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_InternalBuffer.Write((const XnUChar*)&dValue, sizeof(XnDouble)); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = WritePropertyImpl(csModule, csProp, dValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_REAL_PROPERTY); - - nRetVal = ReadStringFromBuffer(pcsModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(pcsProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadInternalBuffer((XnUChar*)pdValue, sizeof(XnDouble)); - XN_IS_STATUS_OK(nRetVal); - - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pdValue); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_STRING_PROPERTY); - - nRetVal = WriteStringToBuffer(csModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(csProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(csValue); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = WritePropertyImpl(csModule, csProp, csValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING_PROPERTY); - - nRetVal = ReadStringFromBuffer(pcsModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(pcsProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(pcsValue); - XN_IS_STATUS_OK(nRetVal); - - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pcsValue); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_GENERAL_PROPERTY); - - nRetVal = WriteStringToBuffer(csModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WriteStringToBuffer(csProp); - XN_IS_STATUS_OK(nRetVal); - - // write buffer size - nRetVal = m_InternalBuffer.Write((const XnUChar*)&gbValue.nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // write buffer - nRetVal = m_InternalBuffer.Write((const XnUChar*)gbValue.pData, gbValue.nDataSize); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = WritePropertyImpl(csModule, csProp, gbValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_GENERAL_PROPERTY); - - nRetVal = ReadStringFromBuffer(pcsModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(pcsProp); - XN_IS_STATUS_OK(nRetVal); - - // convert data into general buffer form - XnGeneralBuffer gb; - nRetVal = ReadInternalBuffer((XnUChar*)&gb.nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - gb.pData = (void*)(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex); - m_nInternalBufferReadIndex += gb.nDataSize; - - *pgbValue = gb; - - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pgbValue); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteStreamData(const XnStreamData* pStreamOutput, XnCodec* pCodec) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_STREAM_DATA); - - // write stream name - nRetVal = WriteStringToBuffer(pStreamOutput->StreamName); - XN_IS_STATUS_OK(nRetVal); - - // write timestamp - nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); - XN_IS_STATUS_OK(nRetVal); - - // write frame-id - nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // write compression format - XnCompressionFormats nFormat = pCodec->GetCompressionFormat(); - nRetVal = m_InternalBuffer.Write((const XnUChar*)&nFormat, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // write original data size - nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // leave space for compressed data size - XnUInt32* pnCompressedDataSize = (XnUInt32*)m_InternalBuffer.GetUnsafeWritePointer(); - *pnCompressedDataSize = m_InternalBuffer.GetFreeSpaceInBuffer(); - m_InternalBuffer.UnsafeUpdateSize(sizeof(XnUInt32)); - - // compress data - nRetVal = pCodec->Compress((const XnUChar*)pStreamOutput->pData, pStreamOutput->nDataSize, m_InternalBuffer.GetUnsafeWritePointer(), pnCompressedDataSize); - XN_IS_STATUS_OK(nRetVal); - - // update size (add compressed data) - m_InternalBuffer.UnsafeUpdateSize(*pnCompressedDataSize); - - EndWritingInternalObject(); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadStreamDataProps(XnStreamData* pStreamOutput, XnCompressionFormats* pnCompression, XnUInt32* pnCompressedSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_DATA); - - // keep last read index (because we only want to know the stream name, without - // actually removing anything from the buffer - XnUInt32 nReadIndexBefore = m_nInternalBufferReadIndex; - - // read stream name - nRetVal = ReadStringFromBuffer(pStreamOutput->StreamName); - XN_IS_STATUS_OK(nRetVal); - - // read timestamp - nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); - XN_IS_STATUS_OK(nRetVal); - - // read frame-id - nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // read compression format - nRetVal = ReadInternalBuffer((XnUChar*)pnCompression, sizeof(XnCompressionFormats)); - XN_IS_STATUS_OK(nRetVal); - - // read data size - nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // read compressed data size - nRetVal = ReadInternalBuffer((XnUChar*)pnCompressedSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // restore read index - m_nInternalBufferReadIndex = nReadIndexBefore; - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadStreamData(XnStreamData* pStreamOutput, XnCodec* pCodec) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_DATA); - - // read stream name - nRetVal = ReadStringFromBuffer(pStreamOutput->StreamName); - XN_IS_STATUS_OK(nRetVal); - - // read timestamp - nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); - XN_IS_STATUS_OK(nRetVal); - - // read frame-id - nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // read compression format - XnCompressionFormats nFormat; - nRetVal = ReadInternalBuffer((XnUChar*)&nFormat, sizeof(XnCompressionFormats)); - XN_IS_STATUS_OK(nRetVal); - - if (nFormat != pCodec->GetCompressionFormat()) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Data in stream is packed with another codec than the one provided!"); - } - - // read original data size - XnUInt32 nDataSize; - nRetVal = ReadInternalBuffer((XnUChar*)&nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - if (pStreamOutput->pInternal->bAllocated && pStreamOutput->pInternal->nAllocSize < nDataSize) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - pStreamOutput->nDataSize = nDataSize; - - // read compressed data size - XnUInt32 nCompressedDataSize; - nRetVal = ReadInternalBuffer((XnUChar*)&nCompressedDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // decompress - nRetVal = pCodec->Decompress(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex, nCompressedDataSize, (XnUChar*)pStreamOutput->pData, &pStreamOutput->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteCustomData(XnUInt32 nObjectType, const void* pData, XnUInt32 nDataSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject((XnPackedDataType)nObjectType); - - // write buffer size - nRetVal = m_InternalBuffer.Write((const XnUChar*)&nDataSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // write buffer - nRetVal = m_InternalBuffer.Write((const XnUChar*)pData, nDataSize); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadCustomData(XnUInt32 nObjectType, void* pData, XnUInt32* pnDataSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(nObjectType); - - // read buffer size - XnUInt32 nSize = 0; - nRetVal = ReadInternalBuffer((XnUChar*)&nSize, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - if (nSize > *pnDataSize) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - nRetVal = ReadInternalBuffer((XnUChar*)pData, nSize); - XN_IS_STATUS_OK(nRetVal); - - *pnDataSize = nSize; - - ResetReadBuffer(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteEnd() -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject(XN_PACKED_END); - EndWritingInternalObject(); - - nRetVal = FlushInternalBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteString(const XnChar* strString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - StartWritingIntenalObject((XnPackedDataType)XN_PACKED_STRING); - - nRetVal = WriteStringToBuffer(strString); - XN_IS_STATUS_OK(nRetVal); - - EndWritingInternalObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadString(XnChar* pcsString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING); - - nRetVal = ReadStringFromBuffer(pcsString); - XN_IS_STATUS_OK(nRetVal); - - MoveToNextObject(); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::FixReadBCObjects() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // keep a pointer to current header (it might change if we read additional objects) - XnPackedDataHeader* pHeader = m_pCurrentHeader; - XnUInt32 nStartReadIndex = m_nInternalBufferReadIndex; - - switch (m_pCurrentHeader->nType) - { - case XN_PACKED_PROPERTY_SET: - { - // check if this is the old version (with size 0) - if (m_nInternalBufferReadIndex != m_InternalBuffer.GetSize()) - { - return (XN_STATUS_OK); - } - - // It is old version. Fix it. - // read all module names (+ modules end marker) - while (TRUE) - { - nRetVal = ReadNextObjectImpl(); - XN_IS_STATUS_OK(nRetVal); - - if (m_pCurrentHeader->nType == XN_PACKED_PROPERTY_SET_MODULES_END_MARKER) - { - break; - } - - // make sure this is a string - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING); - } - - // read properties (+ properties end marker) - while (TRUE) - { - nRetVal = ReadNextObjectImpl(); - XN_IS_STATUS_OK(nRetVal); - - if (m_pCurrentHeader->nType == XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER) - { - break; - } - - // make sure this is a property - if (m_pCurrentHeader->nType != XN_PACKED_INT_PROPERTY && - m_pCurrentHeader->nType != XN_PACKED_REAL_PROPERTY && - m_pCurrentHeader->nType != XN_PACKED_STRING_PROPERTY && - m_pCurrentHeader->nType != XN_PACKED_GENERAL_PROPERTY) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Trying to read object of type property when stream contains object of type %d!", m_pCurrentHeader->nType); - } - } - - break; - } - case XN_PACKED_NEW_STREAM: - { - // check if this is old version (bad size). Read both strings - XnChar strTemp[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = ReadStringFromBuffer(strTemp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadStringFromBuffer(strTemp); - XN_IS_STATUS_OK(nRetVal); - - if (m_nInternalBufferReadIndex != m_InternalBuffer.GetSize()) - { - m_nInternalBufferReadIndex = nStartReadIndex; - return (XN_STATUS_OK); - } - - // read next object - nRetVal = ReadNextObjectImpl(); - XN_IS_STATUS_OK(nRetVal); - - // make sure this is a property set - XN_VALIDATE_OBJECT_TYPE(XN_PACKED_PROPERTY_SET); - - break; - } - default: - // other objects are not BC - return (XN_STATUS_OK); - } - - // move back to start - m_nInternalBufferReadIndex = nStartReadIndex; - // update size accordingly - pHeader->nSize = m_InternalBuffer.GetUnsafeWritePointer() - (XnUChar*)pHeader - sizeof(XnPackedDataHeader); - // now place header back at root object - m_pCurrentHeader = pHeader; - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadNextObjectImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read header - m_pCurrentHeader = (XnPackedDataHeader*)m_InternalBuffer.GetUnsafeWritePointer(); - nRetVal = m_pStream->ReadData((XnUChar*)m_pCurrentHeader, sizeof(XnPackedDataHeader)); - XN_IS_STATUS_OK(nRetVal); - - m_InternalBuffer.UnsafeUpdateSize(sizeof(XnPackedDataHeader)); - m_nInternalBufferReadIndex += sizeof(XnPackedDataHeader); - - // check size - if (m_InternalBuffer.GetFreeSpaceInBuffer() < m_pCurrentHeader->nSize) - { - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - } - - // read data - nRetVal = m_pStream->ReadData(m_InternalBuffer.GetUnsafeWritePointer(), m_pCurrentHeader->nSize); - XN_IS_STATUS_OK(nRetVal); - - m_InternalBuffer.UnsafeUpdateSize(m_pCurrentHeader->nSize); - - // fix BC objects - nRetVal = FixReadBCObjects(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadNextObject(XnPackedDataType* pType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - ResetReadBuffer(); - - nRetVal = ReadNextObjectImpl(); - XN_IS_STATUS_OK(nRetVal); - - *pType = m_pCurrentHeader->nType; - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadInternalBuffer(XnUChar* pData, XnUInt32 nDataSize) -{ - if ((m_InternalBuffer.GetSize() - m_nInternalBufferReadIndex) < nDataSize) - return XN_STATUS_INTERNAL_BUFFER_TOO_SMALL; - - // read - xnOSMemCopy(pData, m_InternalBuffer.GetData() + m_nInternalBufferReadIndex, nDataSize); - - // update read index - m_nInternalBufferReadIndex += nDataSize; - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::WriteStringToBuffer(const XnChar* csString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get length (including null termination) - XnUInt32 nLength = strlen(csString) + 1; - if (nLength >= XN_DEVICE_MAX_STRING_LENGTH) - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - - // write length - nRetVal = m_InternalBuffer.Write((const XnUChar*)&nLength, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - // write string - nRetVal = m_InternalBuffer.Write((const XnUChar*)csString, nLength); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDataPacker::ReadStringFromBuffer(XnChar* pcsString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read length - XnUInt32 nLength; - nRetVal = ReadInternalBuffer((XnUChar*)&nLength, sizeof(XnUInt32)); - XN_IS_STATUS_OK(nRetVal); - - //read string - nRetVal = ReadInternalBuffer((XnUChar*)pcsString, nLength); - XN_IS_STATUS_OK(nRetVal); - - // null terminate the string - pcsString[nLength] = '\0'; - - return (XN_STATUS_OK); -} - -void XnDataPacker::StartWritingIntenalObject(XnUInt32 nType) -{ - m_pCurrentHeader = (XnPackedDataHeader*)m_InternalBuffer.GetUnsafeWritePointer(); - m_InternalBuffer.UnsafeUpdateSize(sizeof(XnPackedDataHeader)); - m_pCurrentHeader->nType = (XnPackedDataType)nType; - m_pCurrentHeader->nSize = 0; -} - -void XnDataPacker::EndWritingInternalObject() -{ - m_pCurrentHeader->nSize = m_InternalBuffer.GetUnsafeWritePointer() - (XnUChar*)m_pCurrentHeader - sizeof(XnPackedDataHeader); -} - -XnStatus XnDataPacker::FlushInternalBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // make sure root header contains entire size (without the header itself) - XnPackedDataHeader* pHeader = (XnPackedDataHeader*)m_InternalBuffer.GetData(); - pHeader->nSize = m_InternalBuffer.GetSize() - sizeof(XnPackedDataHeader); - - nRetVal = m_pStream->WriteData(m_InternalBuffer.GetData(), m_InternalBuffer.GetSize()); - XN_IS_STATUS_OK(nRetVal); - - // reset buffer - m_InternalBuffer.Reset(); - - return (XN_STATUS_OK); -} - -void XnDataPacker::MoveToNextObject() -{ - m_pCurrentHeader = (XnPackedDataHeader*)(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex); - m_nInternalBufferReadIndex += sizeof(XnPackedDataHeader); -} - -void XnDataPacker::ResetReadBuffer() -{ - m_InternalBuffer.Reset(); - m_pCurrentHeader = NULL; - m_nInternalBufferReadIndex = 0; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataPacker.h" +#include +#include +#include +#include "XnStreamDataInternal.h" +#include "XnPropertySetInternal.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_PACKED_STRING 1000 +#define XN_PACKED_PROPERTY_SET_MODULES_END_MARKER 1001 +#define XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER 1002 + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +#pragma pack (push, 1) + +typedef struct XnPackedDataHeader +{ + XnPackedDataType nType; + XnUInt32 nSize; +} XnPackedDataHeader; + +#pragma pack (pop) + +//--------------------------------------------------------------------------- +// Macros +//--------------------------------------------------------------------------- +#define XN_VALIDATE_OBJECT_TYPE(type) \ + if (m_pCurrentHeader == NULL) \ + { \ + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Cannot read an object before a call to ReadNextObject()!"); \ + } \ + if (m_pCurrentHeader->nType != type) \ + { \ + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Trying to read object of type %d when stream contains object of type %d!", type, m_pCurrentHeader->nType); \ + } + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDataPacker::XnDataPacker(XnIOStream* pStream, XnUInt32 nInternalBufferSize) : + m_pStream(pStream), + m_nBufferSize(nInternalBufferSize), + m_nInternalBufferReadIndex(0), + m_pCurrentHeader(NULL) +{ + ResetReadBuffer(); +} + +XnDataPacker::~XnDataPacker() +{ + Free(); +} + +XnStatus XnDataPacker::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // we allocate enough space for the data and the header + nRetVal = m_InternalBuffer.Allocate(m_nBufferSize + sizeof(XnPackedDataHeader)); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::Free() +{ + m_InternalBuffer.Free(); + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteNewStream(const XnChar* strType, const XnChar* strName, const XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_NEW_STREAM); + + nRetVal = WriteStringToBuffer(strType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(strName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WritePropertySetImpl(pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadNewStreamName(XnChar* csType, XnChar* csName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_NEW_STREAM); + + // keep last read index (because we only want to know the stream name, without + // actually removing anything from the buffer + XnUInt32 nReadIndexBefore = m_nInternalBufferReadIndex; + + // read stream type + nRetVal = ReadStringFromBuffer(csType); + XN_IS_STATUS_OK(nRetVal); + + // read stream name + nRetVal = ReadStringFromBuffer(csName); + XN_IS_STATUS_OK(nRetVal); + + // restore read index + m_nInternalBufferReadIndex = nReadIndexBefore; + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadNewStream(XnChar* csType, XnChar* csName, XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_NEW_STREAM); + + nRetVal = ReadStringFromBuffer(csType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(csName); + XN_IS_STATUS_OK(nRetVal); + + MoveToNextObject(); + + nRetVal = ReadPropertySetImpl(pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertySetProperties(const XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnPropertySetData::Iterator it = pSet->pData->begin(); it != pSet->pData->end(); ++it) + { + XnActualPropertiesHash* pModule = it.Value(); + for (XnActualPropertiesHash::ConstIterator itProp = pModule->begin(); itProp != pModule->end(); ++itProp) + { + switch (itProp.Value()->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pProp = (XnActualIntProperty*)itProp.Value(); + nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pProp = (XnActualRealProperty*)itProp.Value(); + nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pProp = (XnActualStringProperty*)itProp.Value(); + nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)itProp.Value(); + nRetVal = WritePropertyImpl(pProp->GetModule(), pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d", itProp.Value()->GetType()); + } + } + } + + StartWritingIntenalObject(XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER); + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertySetImpl(const XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_PROPERTY_SET); + + // Write module names + for (XnPropertySetData::Iterator it = pPropertySet->pData->begin(); it != pPropertySet->pData->end(); ++it) + { + nRetVal = WriteString(it.Key()); + XN_IS_STATUS_OK(nRetVal); + } + + StartWritingIntenalObject(XN_PACKED_PROPERTY_SET_MODULES_END_MARKER); + EndWritingInternalObject(); + + // write properties + nRetVal = WritePropertySetProperties(pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertySet(const XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = WritePropertySetImpl(pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertySetImpl(XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_PROPERTY_SET); + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + + // read property set marker + MoveToNextObject(); + + while (m_pCurrentHeader->nType != XN_PACKED_PROPERTY_SET_MODULES_END_MARKER) + { + nRetVal = ReadString(strModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddModule(pPropertySet, strModule); + XN_IS_STATUS_OK(nRetVal); + } + + // read properties + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + + // read the modules end marker + MoveToNextObject(); + + while (m_pCurrentHeader->nType != XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER) + { + // read property and add it to set + switch (m_pCurrentHeader->nType) + { + case XN_PACKED_INT_PROPERTY: + { + XnUInt64 nValue; + nRetVal = ReadPropertyImpl(strModule, strName, &nValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pPropertySet, strModule, strName, nValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_REAL_PROPERTY: + { + XnDouble dValue; + nRetVal = ReadPropertyImpl(strModule, strName, &dValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddRealProperty(pPropertySet, strModule, strName, dValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_STRING_PROPERTY: + { + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = ReadPropertyImpl(strModule, strName, strValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddStringProperty(pPropertySet, strModule, strName, strValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_GENERAL_PROPERTY: + { + XnGeneralBuffer gbValue; + nRetVal = ReadPropertyImpl(strModule, strName, &gbValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddGeneralProperty(pPropertySet, strModule, strName, &gbValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Stream contains an object of type %d in the middle of a property set!", m_pCurrentHeader->nType); + } + } // props loop + + // read properties end marker + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertySet(XnPropertySet* pPropertySet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReadPropertySetImpl(pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteStreamRemoved(const XnChar* csStreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_STREAM_REMOVED); + + nRetVal = WriteStringToBuffer(csStreamName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadStreamRemoved(XnChar* csStreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_REMOVED); + + nRetVal = ReadStringFromBuffer(csStreamName); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_INT_PROPERTY); + + nRetVal = WriteStringToBuffer(csModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(csProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_InternalBuffer.Write((const XnUChar*)&nValue, sizeof(XnUInt64)); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = WritePropertyImpl(csModule, csProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_INT_PROPERTY); + + nRetVal = ReadStringFromBuffer(pcsModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(pcsProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadInternalBuffer((XnUChar*)pnValue, sizeof(XnUInt64)); + XN_IS_STATUS_OK(nRetVal); + + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pnValue); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_REAL_PROPERTY); + + nRetVal = WriteStringToBuffer(csModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(csProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_InternalBuffer.Write((const XnUChar*)&dValue, sizeof(XnDouble)); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = WritePropertyImpl(csModule, csProp, dValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_REAL_PROPERTY); + + nRetVal = ReadStringFromBuffer(pcsModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(pcsProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadInternalBuffer((XnUChar*)pdValue, sizeof(XnDouble)); + XN_IS_STATUS_OK(nRetVal); + + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pdValue); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_STRING_PROPERTY); + + nRetVal = WriteStringToBuffer(csModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(csProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(csValue); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = WritePropertyImpl(csModule, csProp, csValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING_PROPERTY); + + nRetVal = ReadStringFromBuffer(pcsModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(pcsProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(pcsValue); + XN_IS_STATUS_OK(nRetVal); + + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pcsValue); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_GENERAL_PROPERTY); + + nRetVal = WriteStringToBuffer(csModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WriteStringToBuffer(csProp); + XN_IS_STATUS_OK(nRetVal); + + // write buffer size + nRetVal = m_InternalBuffer.Write((const XnUChar*)&gbValue.nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // write buffer + nRetVal = m_InternalBuffer.Write((const XnUChar*)gbValue.pData, gbValue.nDataSize); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteProperty(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = WritePropertyImpl(csModule, csProp, gbValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_GENERAL_PROPERTY); + + nRetVal = ReadStringFromBuffer(pcsModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(pcsProp); + XN_IS_STATUS_OK(nRetVal); + + // convert data into general buffer form + XnGeneralBuffer gb; + nRetVal = ReadInternalBuffer((XnUChar*)&gb.nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + gb.pData = (void*)(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex); + m_nInternalBufferReadIndex += gb.nDataSize; + + *pgbValue = gb; + + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReadPropertyImpl(pcsModule, pcsProp, pgbValue); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteStreamData(const XnStreamData* pStreamOutput, XnCodec* pCodec) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_STREAM_DATA); + + // write stream name + nRetVal = WriteStringToBuffer(pStreamOutput->StreamName); + XN_IS_STATUS_OK(nRetVal); + + // write timestamp + nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); + XN_IS_STATUS_OK(nRetVal); + + // write frame-id + nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // write compression format + XnCompressionFormats nFormat = pCodec->GetCompressionFormat(); + nRetVal = m_InternalBuffer.Write((const XnUChar*)&nFormat, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // write original data size + nRetVal = m_InternalBuffer.Write((const XnUChar*)&pStreamOutput->nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // leave space for compressed data size + XnUInt32* pnCompressedDataSize = (XnUInt32*)m_InternalBuffer.GetUnsafeWritePointer(); + *pnCompressedDataSize = m_InternalBuffer.GetFreeSpaceInBuffer(); + m_InternalBuffer.UnsafeUpdateSize(sizeof(XnUInt32)); + + // compress data + nRetVal = pCodec->Compress((const XnUChar*)pStreamOutput->pData, pStreamOutput->nDataSize, m_InternalBuffer.GetUnsafeWritePointer(), pnCompressedDataSize); + XN_IS_STATUS_OK(nRetVal); + + // update size (add compressed data) + m_InternalBuffer.UnsafeUpdateSize(*pnCompressedDataSize); + + EndWritingInternalObject(); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadStreamDataProps(XnStreamData* pStreamOutput, XnCompressionFormats* pnCompression, XnUInt32* pnCompressedSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_DATA); + + // keep last read index (because we only want to know the stream name, without + // actually removing anything from the buffer + XnUInt32 nReadIndexBefore = m_nInternalBufferReadIndex; + + // read stream name + nRetVal = ReadStringFromBuffer(pStreamOutput->StreamName); + XN_IS_STATUS_OK(nRetVal); + + // read timestamp + nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); + XN_IS_STATUS_OK(nRetVal); + + // read frame-id + nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // read compression format + nRetVal = ReadInternalBuffer((XnUChar*)pnCompression, sizeof(XnCompressionFormats)); + XN_IS_STATUS_OK(nRetVal); + + // read data size + nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // read compressed data size + nRetVal = ReadInternalBuffer((XnUChar*)pnCompressedSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // restore read index + m_nInternalBufferReadIndex = nReadIndexBefore; + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadStreamData(XnStreamData* pStreamOutput, XnCodec* pCodec) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STREAM_DATA); + + // read stream name + nRetVal = ReadStringFromBuffer(pStreamOutput->StreamName); + XN_IS_STATUS_OK(nRetVal); + + // read timestamp + nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nTimestamp, sizeof(XnUInt64)); + XN_IS_STATUS_OK(nRetVal); + + // read frame-id + nRetVal = ReadInternalBuffer((XnUChar*)&pStreamOutput->nFrameID, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // read compression format + XnCompressionFormats nFormat; + nRetVal = ReadInternalBuffer((XnUChar*)&nFormat, sizeof(XnCompressionFormats)); + XN_IS_STATUS_OK(nRetVal); + + if (nFormat != pCodec->GetCompressionFormat()) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Data in stream is packed with another codec than the one provided!"); + } + + // read original data size + XnUInt32 nDataSize; + nRetVal = ReadInternalBuffer((XnUChar*)&nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + if (pStreamOutput->pInternal->bAllocated && pStreamOutput->pInternal->nAllocSize < nDataSize) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + pStreamOutput->nDataSize = nDataSize; + + // read compressed data size + XnUInt32 nCompressedDataSize; + nRetVal = ReadInternalBuffer((XnUChar*)&nCompressedDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // decompress + nRetVal = pCodec->Decompress(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex, nCompressedDataSize, (XnUChar*)pStreamOutput->pData, &pStreamOutput->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteCustomData(XnUInt32 nObjectType, const void* pData, XnUInt32 nDataSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject((XnPackedDataType)nObjectType); + + // write buffer size + nRetVal = m_InternalBuffer.Write((const XnUChar*)&nDataSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // write buffer + nRetVal = m_InternalBuffer.Write((const XnUChar*)pData, nDataSize); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadCustomData(XnUInt32 nObjectType, void* pData, XnUInt32* pnDataSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(nObjectType); + + // read buffer size + XnUInt32 nSize = 0; + nRetVal = ReadInternalBuffer((XnUChar*)&nSize, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + if (nSize > *pnDataSize) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + nRetVal = ReadInternalBuffer((XnUChar*)pData, nSize); + XN_IS_STATUS_OK(nRetVal); + + *pnDataSize = nSize; + + ResetReadBuffer(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteEnd() +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject(XN_PACKED_END); + EndWritingInternalObject(); + + nRetVal = FlushInternalBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteString(const XnChar* strString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + StartWritingIntenalObject((XnPackedDataType)XN_PACKED_STRING); + + nRetVal = WriteStringToBuffer(strString); + XN_IS_STATUS_OK(nRetVal); + + EndWritingInternalObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadString(XnChar* pcsString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING); + + nRetVal = ReadStringFromBuffer(pcsString); + XN_IS_STATUS_OK(nRetVal); + + MoveToNextObject(); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::FixReadBCObjects() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // keep a pointer to current header (it might change if we read additional objects) + XnPackedDataHeader* pHeader = m_pCurrentHeader; + XnUInt32 nStartReadIndex = m_nInternalBufferReadIndex; + + switch (m_pCurrentHeader->nType) + { + case XN_PACKED_PROPERTY_SET: + { + // check if this is the old version (with size 0) + if (m_nInternalBufferReadIndex != m_InternalBuffer.GetSize()) + { + return (XN_STATUS_OK); + } + + // It is old version. Fix it. + // read all module names (+ modules end marker) + while (TRUE) + { + nRetVal = ReadNextObjectImpl(); + XN_IS_STATUS_OK(nRetVal); + + if (m_pCurrentHeader->nType == XN_PACKED_PROPERTY_SET_MODULES_END_MARKER) + { + break; + } + + // make sure this is a string + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_STRING); + } + + // read properties (+ properties end marker) + while (TRUE) + { + nRetVal = ReadNextObjectImpl(); + XN_IS_STATUS_OK(nRetVal); + + if (m_pCurrentHeader->nType == XN_PACKED_PROPERTY_SET_PROPERTIES_END_MARKER) + { + break; + } + + // make sure this is a property + if (m_pCurrentHeader->nType != XN_PACKED_INT_PROPERTY && + m_pCurrentHeader->nType != XN_PACKED_REAL_PROPERTY && + m_pCurrentHeader->nType != XN_PACKED_STRING_PROPERTY && + m_pCurrentHeader->nType != XN_PACKED_GENERAL_PROPERTY) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Trying to read object of type property when stream contains object of type %d!", m_pCurrentHeader->nType); + } + } + + break; + } + case XN_PACKED_NEW_STREAM: + { + // check if this is old version (bad size). Read both strings + XnChar strTemp[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = ReadStringFromBuffer(strTemp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadStringFromBuffer(strTemp); + XN_IS_STATUS_OK(nRetVal); + + if (m_nInternalBufferReadIndex != m_InternalBuffer.GetSize()) + { + m_nInternalBufferReadIndex = nStartReadIndex; + return (XN_STATUS_OK); + } + + // read next object + nRetVal = ReadNextObjectImpl(); + XN_IS_STATUS_OK(nRetVal); + + // make sure this is a property set + XN_VALIDATE_OBJECT_TYPE(XN_PACKED_PROPERTY_SET); + + break; + } + default: + // other objects are not BC + return (XN_STATUS_OK); + } + + // move back to start + m_nInternalBufferReadIndex = nStartReadIndex; + // update size accordingly + pHeader->nSize = m_InternalBuffer.GetUnsafeWritePointer() - (XnUChar*)pHeader - sizeof(XnPackedDataHeader); + // now place header back at root object + m_pCurrentHeader = pHeader; + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadNextObjectImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read header + m_pCurrentHeader = (XnPackedDataHeader*)m_InternalBuffer.GetUnsafeWritePointer(); + nRetVal = m_pStream->ReadData((XnUChar*)m_pCurrentHeader, sizeof(XnPackedDataHeader)); + XN_IS_STATUS_OK(nRetVal); + + m_InternalBuffer.UnsafeUpdateSize(sizeof(XnPackedDataHeader)); + m_nInternalBufferReadIndex += sizeof(XnPackedDataHeader); + + // check size + if (m_InternalBuffer.GetFreeSpaceInBuffer() < m_pCurrentHeader->nSize) + { + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + } + + // read data + nRetVal = m_pStream->ReadData(m_InternalBuffer.GetUnsafeWritePointer(), m_pCurrentHeader->nSize); + XN_IS_STATUS_OK(nRetVal); + + m_InternalBuffer.UnsafeUpdateSize(m_pCurrentHeader->nSize); + + // fix BC objects + nRetVal = FixReadBCObjects(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadNextObject(XnPackedDataType* pType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + ResetReadBuffer(); + + nRetVal = ReadNextObjectImpl(); + XN_IS_STATUS_OK(nRetVal); + + *pType = m_pCurrentHeader->nType; + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadInternalBuffer(XnUChar* pData, XnUInt32 nDataSize) +{ + if ((m_InternalBuffer.GetSize() - m_nInternalBufferReadIndex) < nDataSize) + return XN_STATUS_INTERNAL_BUFFER_TOO_SMALL; + + // read + xnOSMemCopy(pData, m_InternalBuffer.GetData() + m_nInternalBufferReadIndex, nDataSize); + + // update read index + m_nInternalBufferReadIndex += nDataSize; + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::WriteStringToBuffer(const XnChar* csString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get length (including null termination) + XnUInt32 nLength = strlen(csString) + 1; + if (nLength >= XN_DEVICE_MAX_STRING_LENGTH) + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + + // write length + nRetVal = m_InternalBuffer.Write((const XnUChar*)&nLength, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + // write string + nRetVal = m_InternalBuffer.Write((const XnUChar*)csString, nLength); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDataPacker::ReadStringFromBuffer(XnChar* pcsString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read length + XnUInt32 nLength; + nRetVal = ReadInternalBuffer((XnUChar*)&nLength, sizeof(XnUInt32)); + XN_IS_STATUS_OK(nRetVal); + + //read string + nRetVal = ReadInternalBuffer((XnUChar*)pcsString, nLength); + XN_IS_STATUS_OK(nRetVal); + + // null terminate the string + pcsString[nLength] = '\0'; + + return (XN_STATUS_OK); +} + +void XnDataPacker::StartWritingIntenalObject(XnUInt32 nType) +{ + m_pCurrentHeader = (XnPackedDataHeader*)m_InternalBuffer.GetUnsafeWritePointer(); + m_InternalBuffer.UnsafeUpdateSize(sizeof(XnPackedDataHeader)); + m_pCurrentHeader->nType = (XnPackedDataType)nType; + m_pCurrentHeader->nSize = 0; +} + +void XnDataPacker::EndWritingInternalObject() +{ + m_pCurrentHeader->nSize = m_InternalBuffer.GetUnsafeWritePointer() - (XnUChar*)m_pCurrentHeader - sizeof(XnPackedDataHeader); +} + +XnStatus XnDataPacker::FlushInternalBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // make sure root header contains entire size (without the header itself) + XnPackedDataHeader* pHeader = (XnPackedDataHeader*)m_InternalBuffer.GetData(); + pHeader->nSize = m_InternalBuffer.GetSize() - sizeof(XnPackedDataHeader); + + nRetVal = m_pStream->WriteData(m_InternalBuffer.GetData(), m_InternalBuffer.GetSize()); + XN_IS_STATUS_OK(nRetVal); + + // reset buffer + m_InternalBuffer.Reset(); + + return (XN_STATUS_OK); +} + +void XnDataPacker::MoveToNextObject() +{ + m_pCurrentHeader = (XnPackedDataHeader*)(m_InternalBuffer.GetData() + m_nInternalBufferReadIndex); + m_nInternalBufferReadIndex += sizeof(XnPackedDataHeader); +} + +void XnDataPacker::ResetReadBuffer() +{ + m_InternalBuffer.Reset(); + m_pCurrentHeader = NULL; + m_nInternalBufferReadIndex = 0; +} diff --git a/Source/XnDDK/XnDataPacker.h b/Source/XnDDK/XnDataPacker.h index 064c469..bcf2ad6 100644 --- a/Source/XnDDK/XnDataPacker.h +++ b/Source/XnDDK/XnDataPacker.h @@ -1,306 +1,306 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DATA_PACKER_H__ -#define __XN_DATA_PACKER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef enum -{ - XN_PACKED_PROPERTY_SET = 1, - XN_PACKED_NEW_STREAM = 2, - XN_PACKED_INT_PROPERTY = 3, - XN_PACKED_REAL_PROPERTY = 4, - XN_PACKED_STRING_PROPERTY = 5, - XN_PACKED_GENERAL_PROPERTY = 6, - XN_PACKED_STREAM_REMOVED = 7, - XN_PACKED_STREAM_DATA = 8, - XN_PACKED_END = 9, - XN_PACKED_CUSTOM_MESSAGE = 2000, -} XnPackedDataType; - -struct XnPackedDataHeader; // Forward declaration - -/** -* A helper class for packing and unpacking PS data from IO streams. -*/ -class XN_DDK_CPP_API XnDataPacker -{ -public: - /** - * Creates a DataPacker object. - * - * @param pStream [in] The stream to read/write data from/to. - * @param nInternalBufferSize [in] The internal buffer size. This should be the maximum written/read object size. - */ - XnDataPacker(XnIOStream* pStream, XnUInt32 nInternalBufferSize); - - /** - * Destroys a DataPacker object. - */ - ~XnDataPacker(); - - /** - * Initialized the DataPacker object. - */ - XnStatus Init(); - - /** - * Frees the DataPacker object. - */ - XnStatus Free(); - - /** - * Writes a new stream into the stream. - * - * @param strType [in] The type of the stream. - * @param strName [in] The name of the stream. - * @param pPropertySet [in] The property set to write. - */ - XnStatus WriteNewStream(const XnChar* strType, const XnChar* strName, const XnPropertySet* pPropertySet); - - /** - * Writes stream removal into the stream. - * - * @param csStreamName [in] The name of the stream. - */ - XnStatus WriteStreamRemoved(const XnChar* csStreamName); - - /** - * Writes a property set into the stream. - * - * @param pPropertySet [in] The property set to write. - */ - XnStatus WritePropertySet(const XnPropertySet* pPropertySet); - - /** - * Writes an int property into the stream. - * - * @param csModuleName [in] The name of the module. - * @param csProp [in] The name of the property. - * @param nValue [in] The value of the property. - */ - XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue); - /** - * Writes a real property into the stream. - * - * @param csModuleName [in] The name of the module. - * @param csProp [in] The name of the property. - * @param dValue [in] The value of the property. - */ - XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnDouble dValue); - /** - * Writes a string property into the stream. - * - * @param csModuleName [in] The name of the module. - * @param csProp [in] The name of the property. - * @param csValue [in] The value of the property. - */ - XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue); - /** - * Writes a general property into the stream. - * - * @param csModuleName [in] The name of the module. - * @param csProp [in] The name of the property. - * @param gbValue [in] The value of the property. - */ - XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue); - /** - * Writes a stream data object into the stream, compressing the data using the given codec. - * - * @param pStreamOutput [in] The stream output object to write. - * @param pCodec [in] The codec that should be used to compress the data. - */ - XnStatus WriteStreamData(const XnStreamData* pStreamOutput, XnCodec* pCodec); - - /** - * Writes a custom data object into the stream. - * - * @param nObjectType [in] The type of the object being written. - * @param pData [in] A pointer to the data to be written. - * @param nDataSize [in] The size of the written data. - */ - XnStatus WriteCustomData(XnUInt32 nObjectType, const void* pData, XnUInt32 nDataSize); - - /** - * Writes a marker telling this is the end of the stream. - */ - XnStatus WriteEnd(); - - /** - * Reads a single object from the IO stream into the internal buffer, and returns the type - * of that object. - * - * @param pType [out] The type of the object that was read from the stream. - */ - XnStatus ReadNextObject(XnPackedDataType* pType); - - /** - * Reads a new stream name event from the internal buffer. - * - * @param csType [in/out] A string to be filled with the stream type. - * @param csName [in/out] A string to be filled with the stream name. - */ - XnStatus ReadNewStreamName(XnChar* csType, XnChar* csName); - - /** - * Reads a new module event from the internal buffer. - * - * @param csModuleName [in/out] A string to be filled with the module name. - * @param pPropertySet [in/out] A property set to be filled with the stream properties. - */ - XnStatus ReadNewStream(XnChar* csType, XnChar* csName, XnPropertySet* pPropertySet); - - /** - * Reads a stream removal event from the internal buffer. - * - * @param csStreamName [in/out] A string to be filled with the stream name. - */ - XnStatus ReadStreamRemoved(XnChar* csStreamName); - - /** - * Reads a property set from the internal buffer. - * - * @param pPropertySet [in/out] A property set to be filled with the stream properties. - */ - XnStatus ReadPropertySet(XnPropertySet* pPropertySet); - - /** - * Reads an int property from the internal buffer. - * - * @param pcsModule [in/out] A string to be filled with the module name. - * @param pcsProp [in/out] A string to be filled with the property name. - * @param pnValue [out] The value of the property. - */ - XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue); - /** - * Reads a real property from the internal buffer. - * - * @param pcsModule [in/out] A string to be filled with the module name. - * @param pcsProp [in/out] A string to be filled with the property name. - * @param pdValue [out] The value of the property. - */ - XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue); - /** - * Reads a string property from the internal buffer. - * - * @param pcsModule [in/out] A string to be filled with the module name. - * @param pcsProp [in/out] A string to be filled with the property name. - * @param pcsValue [in/out] A string to be filled with the property value. - */ - XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue); - - /** - * Reads a general property from the internal buffer. - * - * @param pcsModule [in/out] A string to be filled with the module name. - * @param pcsProp [in/out] A string to be filled with the property name. - * @param pgbValue [out] A pointer to a general buffer, that, upon return will point to the data. The user should copy this data. - */ - XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue); - - /** - * Reads properties of a stream data. - * - * @param pStreamOutput [in/out] A stream data object. All its fields will be populated, except for the actual data. - * @param pnCompression [out] Compression format. - * @param pnCompressedSize [out] Compressed Data Size. - */ - XnStatus ReadStreamDataProps(XnStreamData* pStreamOutput, XnCompressionFormats* pnCompression, XnUInt32* pnCompressedSize); - - /** - * Reads a stream data object from the internal buffer, decompressing the data using the given codec. - * - * @param pStreamOutput [in/out] A stream output object to be filled from the stream. - * @param pCodec [in] The codec that should be used to decompress the data. - */ - XnStatus ReadStreamData(XnStreamData* pStreamOutput, XnCodec* pCodec); - - /** - * Reads a custom data from the internal buffer. - * - * @param nObjectType [in] The expected object type. - * @param pData [in] A pointer to a buffer to be filled with data. - * @param nDataSize [in/out] in: Max allowed size, out: Received size - */ - XnStatus ReadCustomData(XnUInt32 nObjectType, void* pData, XnUInt32* pnDataSize); - -private: - /** Starts an internal object. */ - void StartWritingIntenalObject(XnUInt32 nType); - /** Ends an internal object. */ - void EndWritingInternalObject(); - /** End an entire object and write it to stream. */ - XnStatus FlushInternalBuffer(); - - /* Reads the next object into the internal buffer (appending it) */ - XnStatus ReadNextObjectImpl(); - /* If read object is BC, make it look like a new one. */ - XnStatus FixReadBCObjects(); - - void MoveToNextObject(); - - XnStatus WritePropertySetImpl(const XnPropertySet* pPropertySet); - XnStatus WritePropertySetProperties(const XnPropertySet* pPropertySet); - XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue); - XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnDouble dValue); - XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue); - XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue); - XnStatus WriteString(const XnChar* pcsString); - - XnStatus ReadPropertySetImpl(XnPropertySet* pSet); - XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue); - XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue); - XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue); - XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue); - XnStatus ReadString(XnChar* pcsString); - - XnStatus ReadInternalBuffer(XnUChar* pData, XnUInt32 nDataSize); - XnStatus WriteStringToBuffer(const XnChar* csString); - XnStatus ReadStringFromBuffer(XnChar* pcsString); - - void ResetReadBuffer(); - - XnIOStream* m_pStream; - XnUInt32 m_nBufferSize; - XnBuffer m_InternalBuffer; - XnPackedDataHeader* m_pCurrentHeader; - XnUInt32 m_nInternalBufferReadIndex; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DATA_PACKER_H__ +#define __XN_DATA_PACKER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef enum +{ + XN_PACKED_PROPERTY_SET = 1, + XN_PACKED_NEW_STREAM = 2, + XN_PACKED_INT_PROPERTY = 3, + XN_PACKED_REAL_PROPERTY = 4, + XN_PACKED_STRING_PROPERTY = 5, + XN_PACKED_GENERAL_PROPERTY = 6, + XN_PACKED_STREAM_REMOVED = 7, + XN_PACKED_STREAM_DATA = 8, + XN_PACKED_END = 9, + XN_PACKED_CUSTOM_MESSAGE = 2000, +} XnPackedDataType; + +struct XnPackedDataHeader; // Forward declaration + +/** +* A helper class for packing and unpacking PS data from IO streams. +*/ +class XN_DDK_CPP_API XnDataPacker +{ +public: + /** + * Creates a DataPacker object. + * + * @param pStream [in] The stream to read/write data from/to. + * @param nInternalBufferSize [in] The internal buffer size. This should be the maximum written/read object size. + */ + XnDataPacker(XnIOStream* pStream, XnUInt32 nInternalBufferSize); + + /** + * Destroys a DataPacker object. + */ + ~XnDataPacker(); + + /** + * Initialized the DataPacker object. + */ + XnStatus Init(); + + /** + * Frees the DataPacker object. + */ + XnStatus Free(); + + /** + * Writes a new stream into the stream. + * + * @param strType [in] The type of the stream. + * @param strName [in] The name of the stream. + * @param pPropertySet [in] The property set to write. + */ + XnStatus WriteNewStream(const XnChar* strType, const XnChar* strName, const XnPropertySet* pPropertySet); + + /** + * Writes stream removal into the stream. + * + * @param csStreamName [in] The name of the stream. + */ + XnStatus WriteStreamRemoved(const XnChar* csStreamName); + + /** + * Writes a property set into the stream. + * + * @param pPropertySet [in] The property set to write. + */ + XnStatus WritePropertySet(const XnPropertySet* pPropertySet); + + /** + * Writes an int property into the stream. + * + * @param csModuleName [in] The name of the module. + * @param csProp [in] The name of the property. + * @param nValue [in] The value of the property. + */ + XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue); + /** + * Writes a real property into the stream. + * + * @param csModuleName [in] The name of the module. + * @param csProp [in] The name of the property. + * @param dValue [in] The value of the property. + */ + XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnDouble dValue); + /** + * Writes a string property into the stream. + * + * @param csModuleName [in] The name of the module. + * @param csProp [in] The name of the property. + * @param csValue [in] The value of the property. + */ + XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue); + /** + * Writes a general property into the stream. + * + * @param csModuleName [in] The name of the module. + * @param csProp [in] The name of the property. + * @param gbValue [in] The value of the property. + */ + XnStatus WriteProperty(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue); + /** + * Writes a stream data object into the stream, compressing the data using the given codec. + * + * @param pStreamOutput [in] The stream output object to write. + * @param pCodec [in] The codec that should be used to compress the data. + */ + XnStatus WriteStreamData(const XnStreamData* pStreamOutput, XnCodec* pCodec); + + /** + * Writes a custom data object into the stream. + * + * @param nObjectType [in] The type of the object being written. + * @param pData [in] A pointer to the data to be written. + * @param nDataSize [in] The size of the written data. + */ + XnStatus WriteCustomData(XnUInt32 nObjectType, const void* pData, XnUInt32 nDataSize); + + /** + * Writes a marker telling this is the end of the stream. + */ + XnStatus WriteEnd(); + + /** + * Reads a single object from the IO stream into the internal buffer, and returns the type + * of that object. + * + * @param pType [out] The type of the object that was read from the stream. + */ + XnStatus ReadNextObject(XnPackedDataType* pType); + + /** + * Reads a new stream name event from the internal buffer. + * + * @param csType [in/out] A string to be filled with the stream type. + * @param csName [in/out] A string to be filled with the stream name. + */ + XnStatus ReadNewStreamName(XnChar* csType, XnChar* csName); + + /** + * Reads a new module event from the internal buffer. + * + * @param csModuleName [in/out] A string to be filled with the module name. + * @param pPropertySet [in/out] A property set to be filled with the stream properties. + */ + XnStatus ReadNewStream(XnChar* csType, XnChar* csName, XnPropertySet* pPropertySet); + + /** + * Reads a stream removal event from the internal buffer. + * + * @param csStreamName [in/out] A string to be filled with the stream name. + */ + XnStatus ReadStreamRemoved(XnChar* csStreamName); + + /** + * Reads a property set from the internal buffer. + * + * @param pPropertySet [in/out] A property set to be filled with the stream properties. + */ + XnStatus ReadPropertySet(XnPropertySet* pPropertySet); + + /** + * Reads an int property from the internal buffer. + * + * @param pcsModule [in/out] A string to be filled with the module name. + * @param pcsProp [in/out] A string to be filled with the property name. + * @param pnValue [out] The value of the property. + */ + XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue); + /** + * Reads a real property from the internal buffer. + * + * @param pcsModule [in/out] A string to be filled with the module name. + * @param pcsProp [in/out] A string to be filled with the property name. + * @param pdValue [out] The value of the property. + */ + XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue); + /** + * Reads a string property from the internal buffer. + * + * @param pcsModule [in/out] A string to be filled with the module name. + * @param pcsProp [in/out] A string to be filled with the property name. + * @param pcsValue [in/out] A string to be filled with the property value. + */ + XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue); + + /** + * Reads a general property from the internal buffer. + * + * @param pcsModule [in/out] A string to be filled with the module name. + * @param pcsProp [in/out] A string to be filled with the property name. + * @param pgbValue [out] A pointer to a general buffer, that, upon return will point to the data. The user should copy this data. + */ + XnStatus ReadProperty(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue); + + /** + * Reads properties of a stream data. + * + * @param pStreamOutput [in/out] A stream data object. All its fields will be populated, except for the actual data. + * @param pnCompression [out] Compression format. + * @param pnCompressedSize [out] Compressed Data Size. + */ + XnStatus ReadStreamDataProps(XnStreamData* pStreamOutput, XnCompressionFormats* pnCompression, XnUInt32* pnCompressedSize); + + /** + * Reads a stream data object from the internal buffer, decompressing the data using the given codec. + * + * @param pStreamOutput [in/out] A stream output object to be filled from the stream. + * @param pCodec [in] The codec that should be used to decompress the data. + */ + XnStatus ReadStreamData(XnStreamData* pStreamOutput, XnCodec* pCodec); + + /** + * Reads a custom data from the internal buffer. + * + * @param nObjectType [in] The expected object type. + * @param pData [in] A pointer to a buffer to be filled with data. + * @param nDataSize [in/out] in: Max allowed size, out: Received size + */ + XnStatus ReadCustomData(XnUInt32 nObjectType, void* pData, XnUInt32* pnDataSize); + +private: + /** Starts an internal object. */ + void StartWritingIntenalObject(XnUInt32 nType); + /** Ends an internal object. */ + void EndWritingInternalObject(); + /** End an entire object and write it to stream. */ + XnStatus FlushInternalBuffer(); + + /* Reads the next object into the internal buffer (appending it) */ + XnStatus ReadNextObjectImpl(); + /* If read object is BC, make it look like a new one. */ + XnStatus FixReadBCObjects(); + + void MoveToNextObject(); + + XnStatus WritePropertySetImpl(const XnPropertySet* pPropertySet); + XnStatus WritePropertySetProperties(const XnPropertySet* pPropertySet); + XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnUInt64 nValue); + XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnDouble dValue); + XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, const XnChar* csValue); + XnStatus WritePropertyImpl(const XnChar* csModule, const XnChar* csProp, XnGeneralBuffer gbValue); + XnStatus WriteString(const XnChar* pcsString); + + XnStatus ReadPropertySetImpl(XnPropertySet* pSet); + XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnUInt64* pnValue); + XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnDouble* pdValue); + XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnChar* pcsValue); + XnStatus ReadPropertyImpl(XnChar* pcsModule, XnChar* pcsProp, XnGeneralBuffer* pgbValue); + XnStatus ReadString(XnChar* pcsString); + + XnStatus ReadInternalBuffer(XnUChar* pData, XnUInt32 nDataSize); + XnStatus WriteStringToBuffer(const XnChar* csString); + XnStatus ReadStringFromBuffer(XnChar* pcsString); + + void ResetReadBuffer(); + + XnIOStream* m_pStream; + XnUInt32 m_nBufferSize; + XnBuffer m_InternalBuffer; + XnPackedDataHeader* m_pCurrentHeader; + XnUInt32 m_nInternalBufferReadIndex; +}; + #endif //__XN_DATA_PACKER_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDepthStream.cpp b/Source/XnDDK/XnDepthStream.cpp index 06c8fc6..4e93f50 100644 --- a/Source/XnDDK/XnDepthStream.cpp +++ b/Source/XnDDK/XnDepthStream.cpp @@ -1,178 +1,178 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDepthStream.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEPTH_STREAM_MAX_DEPTH_VALUE XN_MAX_UINT16 -#define XN_DEPTH_STREAM_DEFAULT_PIXEL_SIZE_FACTOR 1 - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDepthStream::XnDepthStream(const XnChar* csName, XnBool bAllowCustomResolutions, XnDepthPixel nDeviceMaxDepth, XnUInt16 nDeviceMaxShift) : - XnPixelStream(XN_STREAM_TYPE_DEPTH, csName, bAllowCustomResolutions), - m_MinDepth(XN_STREAM_PROPERTY_MIN_DEPTH), - m_MaxDepth(XN_STREAM_PROPERTY_MAX_DEPTH, nDeviceMaxDepth), - m_ConstShift(XN_STREAM_PROPERTY_CONST_SHIFT), - m_PixelSizeFactor(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, 1), - m_MaxShift(XN_STREAM_PROPERTY_MAX_SHIFT, nDeviceMaxShift), - m_DeviceMaxDepth(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, nDeviceMaxDepth), - m_ParamCoefficient(XN_STREAM_PROPERTY_PARAM_COEFF), - m_ShiftScale(XN_STREAM_PROPERTY_SHIFT_SCALE), - m_ZeroPlaneDistance(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE), - m_ZeroPlanePixelSize(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE), - m_EmitterDCmosDistance(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE), - m_NoDepthValue(XN_STREAM_PROPERTY_NO_SAMPLE), - m_ShadowValue(XN_STREAM_PROPERTY_SHADOW), - m_S2DHelper(this) -{ - m_MinDepth.UpdateSetCallback(SetMinDepthCallback, this); - m_MaxDepth.UpdateSetCallback(SetMaxDepthCallback, this); -} - -XnStatus XnDepthStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnPixelStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - // add properties - XN_VALIDATE_ADD_PROPERTIES(this, &m_MinDepth, &m_MaxDepth, &m_ConstShift, &m_PixelSizeFactor, - &m_MaxShift, &m_ParamCoefficient, &m_ShiftScale, &m_ZeroPlaneDistance, &m_ZeroPlanePixelSize, - &m_EmitterDCmosDistance, &m_NoDepthValue, &m_ShadowValue, &m_DeviceMaxDepth); - - nRetVal = m_S2DHelper.Init(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDepthStream::Free() -{ - XnPixelStream::Free(); - return (XN_STATUS_OK); -} - -XnStatus XnDepthStream::SetMinDepth(XnDepthPixel nMinDepth) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (nMinDepth > GetDeviceMaxDepth()) - { - return XN_STATUS_DEVICE_BAD_PARAM; - } - - nRetVal = m_MinDepth.UnsafeUpdateValue(nMinDepth); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDepthStream::SetMaxDepth(XnDepthPixel nMaxDepth) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (nMaxDepth > GetDeviceMaxDepth()) - { - return XN_STATUS_DEVICE_BAD_PARAM; - } - - nRetVal = m_MaxDepth.UnsafeUpdateValue(nMaxDepth); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDepthStream::ValidateDepthValue(XnDepthPixel nDepth) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (nDepth < 0 || nDepth > GetDeviceMaxDepth()) - { - return XN_STATUS_DEVICE_BAD_PARAM; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDepthStream::OnOutputFormatChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // update no-depth and shadow values - XnDepthPixel nNoValue; - XnDepthPixel nShadowValue; - - switch (GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - nNoValue = 2047; - nShadowValue = 0; - break; - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - nNoValue = 0; - nShadowValue = 1; - break; - default: - XN_LOG_ERROR_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "DepthStream: Unknown output format!") - } - - nRetVal = m_NoDepthValue.UnsafeUpdateValue(nNoValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_ShadowValue.UnsafeUpdateValue(nShadowValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnDepthStream::SetMinDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDepthStream* pStream = (XnDepthStream*)pCookie; - return pStream->SetMinDepth((XnDepthPixel)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnDepthStream::SetMaxDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDepthStream* pStream = (XnDepthStream*)pCookie; - return pStream->SetMaxDepth((XnDepthPixel)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnDepthStream::OutputFormatValueChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnDepthStream* pStream = (XnDepthStream*)pCookie; - return pStream->OnOutputFormatChanged(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDepthStream.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEPTH_STREAM_MAX_DEPTH_VALUE XN_MAX_UINT16 +#define XN_DEPTH_STREAM_DEFAULT_PIXEL_SIZE_FACTOR 1 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDepthStream::XnDepthStream(const XnChar* csName, XnBool bAllowCustomResolutions, XnDepthPixel nDeviceMaxDepth, XnUInt16 nDeviceMaxShift) : + XnPixelStream(XN_STREAM_TYPE_DEPTH, csName, bAllowCustomResolutions), + m_MinDepth(XN_STREAM_PROPERTY_MIN_DEPTH), + m_MaxDepth(XN_STREAM_PROPERTY_MAX_DEPTH, nDeviceMaxDepth), + m_ConstShift(XN_STREAM_PROPERTY_CONST_SHIFT), + m_PixelSizeFactor(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, 1), + m_MaxShift(XN_STREAM_PROPERTY_MAX_SHIFT, nDeviceMaxShift), + m_DeviceMaxDepth(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, nDeviceMaxDepth), + m_ParamCoefficient(XN_STREAM_PROPERTY_PARAM_COEFF), + m_ShiftScale(XN_STREAM_PROPERTY_SHIFT_SCALE), + m_ZeroPlaneDistance(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE), + m_ZeroPlanePixelSize(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE), + m_EmitterDCmosDistance(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE), + m_NoDepthValue(XN_STREAM_PROPERTY_NO_SAMPLE), + m_ShadowValue(XN_STREAM_PROPERTY_SHADOW), + m_S2DHelper(this) +{ + m_MinDepth.UpdateSetCallback(SetMinDepthCallback, this); + m_MaxDepth.UpdateSetCallback(SetMaxDepthCallback, this); +} + +XnStatus XnDepthStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnPixelStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + // add properties + XN_VALIDATE_ADD_PROPERTIES(this, &m_MinDepth, &m_MaxDepth, &m_ConstShift, &m_PixelSizeFactor, + &m_MaxShift, &m_ParamCoefficient, &m_ShiftScale, &m_ZeroPlaneDistance, &m_ZeroPlanePixelSize, + &m_EmitterDCmosDistance, &m_NoDepthValue, &m_ShadowValue, &m_DeviceMaxDepth); + + nRetVal = m_S2DHelper.Init(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDepthStream::Free() +{ + XnPixelStream::Free(); + return (XN_STATUS_OK); +} + +XnStatus XnDepthStream::SetMinDepth(XnDepthPixel nMinDepth) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (nMinDepth > GetDeviceMaxDepth()) + { + return XN_STATUS_DEVICE_BAD_PARAM; + } + + nRetVal = m_MinDepth.UnsafeUpdateValue(nMinDepth); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDepthStream::SetMaxDepth(XnDepthPixel nMaxDepth) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (nMaxDepth > GetDeviceMaxDepth()) + { + return XN_STATUS_DEVICE_BAD_PARAM; + } + + nRetVal = m_MaxDepth.UnsafeUpdateValue(nMaxDepth); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDepthStream::ValidateDepthValue(XnDepthPixel nDepth) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (nDepth < 0 || nDepth > GetDeviceMaxDepth()) + { + return XN_STATUS_DEVICE_BAD_PARAM; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDepthStream::OnOutputFormatChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // update no-depth and shadow values + XnDepthPixel nNoValue; + XnDepthPixel nShadowValue; + + switch (GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + nNoValue = 2047; + nShadowValue = 0; + break; + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + nNoValue = 0; + nShadowValue = 1; + break; + default: + XN_LOG_ERROR_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "DepthStream: Unknown output format!") + } + + nRetVal = m_NoDepthValue.UnsafeUpdateValue(nNoValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_ShadowValue.UnsafeUpdateValue(nShadowValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnDepthStream::SetMinDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDepthStream* pStream = (XnDepthStream*)pCookie; + return pStream->SetMinDepth((XnDepthPixel)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnDepthStream::SetMaxDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDepthStream* pStream = (XnDepthStream*)pCookie; + return pStream->SetMaxDepth((XnDepthPixel)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnDepthStream::OutputFormatValueChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnDepthStream* pStream = (XnDepthStream*)pCookie; + return pStream->OnOutputFormatChanged(); +} diff --git a/Source/XnDDK/XnDepthStream.h b/Source/XnDDK/XnDepthStream.h index 75e7957..3c7b3d0 100644 --- a/Source/XnDDK/XnDepthStream.h +++ b/Source/XnDDK/XnDepthStream.h @@ -1,131 +1,131 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEPTH_STREAM_H__ -#define __XN_DEPTH_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XN_DDK_CPP_API XnDepthStream : public XnPixelStream -{ -public: - XnDepthStream(const XnChar* csName, XnBool bAllowCustomResolutions, XnDepthPixel nDeviceMaxDepth, XnUInt16 nDeviceMaxShift); - ~XnDepthStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnDepthPixel GetMinDepth() const { return (XnDepthPixel)m_MinDepth.GetValue(); } - inline XnDepthPixel GetMaxDepth() const { return (XnDepthPixel)m_MaxDepth.GetValue(); } - inline XnUInt32 GetConstShift() const { return (XnUInt32)m_ConstShift.GetValue(); } - inline XnUInt32 GetPixelSizeFactor() const { return (XnUInt32)m_PixelSizeFactor.GetValue(); } - inline XnUInt16 GetMaxShift() const { return (XnUInt16)m_MaxShift.GetValue(); } - inline XnDepthPixel GetDeviceMaxDepth() const { return (XnDepthPixel)m_DeviceMaxDepth.GetValue(); } - inline XnUInt32 GetParamCoefficient() const { return (XnUInt32)m_ParamCoefficient.GetValue(); } - inline XnUInt32 GetShiftScale() const { return (XnUInt32)m_ShiftScale.GetValue(); } - inline XnDepthPixel GetZeroPlaneDistance() const { return (XnDepthPixel)m_ZeroPlaneDistance.GetValue(); } - inline XnDouble GetZeroPlanePixelSize() const { return m_ZeroPlanePixelSize.GetValue(); } - inline XnDouble GetEmitterDCmosDistance() const { return m_EmitterDCmosDistance.GetValue(); } - inline XnDepthPixel GetNoDepthValue() const { return (XnDepthPixel)m_NoDepthValue.GetValue(); } - inline XnDepthPixel GetShadowValue() const { return (XnDepthPixel)m_ShadowValue.GetValue(); } - - inline XnDepthPixel* GetShiftToDepthTable() const { return m_S2DHelper.GetShiftToDepthTable(); } - inline XnUInt16* GetDepthToShiftTable() const { return m_S2DHelper.GetDepthToShiftTable(); } - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& MinDepthProperty() { return m_MinDepth; } - inline XnActualIntProperty& MaxDepthProperty() { return m_MaxDepth; } - inline XnActualIntProperty& ConstShiftProperty() { return m_ConstShift; } - inline XnActualIntProperty& PixelSizeFactorProperty() { return m_PixelSizeFactor; } - inline XnActualIntProperty& MaxShiftProperty() { return m_MaxShift; } - inline XnActualIntProperty& DeviceMaxDepthProperty() { return m_DeviceMaxDepth; } - inline XnActualIntProperty& ParamCoefficientProperty() { return m_ParamCoefficient; } - inline XnActualIntProperty& ShiftScaleProperty() { return m_ShiftScale; } - inline XnActualIntProperty& ZeroPlaneDistanceProperty() { return m_ZeroPlaneDistance; } - inline XnActualRealProperty& ZeroPlanePixelSizeProperty() { return m_ZeroPlanePixelSize; } - inline XnActualRealProperty& EmitterDCmosDistanceProperty() { return m_EmitterDCmosDistance; } - inline XnActualIntProperty& NoDepthValueProperty() { return m_NoDepthValue; } - inline XnActualIntProperty& ShadowValueProperty() { return m_ShadowValue; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetMinDepth(XnDepthPixel nMinDepth); - virtual XnStatus SetMaxDepth(XnDepthPixel nMaxDepth); - -protected: - //--------------------------------------------------------------------------- - // Helper functions - //--------------------------------------------------------------------------- - XnStatus ValidateDepthValue(XnDepthPixel nDepth); - -private: - XnStatus OnOutputFormatChanged(); - - // callbacks - static XnStatus XN_CALLBACK_TYPE SetMinDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetMaxDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE OutputFormatValueChangedCallback(const XnProperty* pSender, void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_MinDepth; - XnActualIntProperty m_MaxDepth; - XnActualIntProperty m_ConstShift; - XnActualIntProperty m_PixelSizeFactor; - XnActualIntProperty m_MaxShift; - XnActualIntProperty m_DeviceMaxDepth; - XnActualIntProperty m_ParamCoefficient; - XnActualIntProperty m_ShiftScale; - XnActualIntProperty m_ZeroPlaneDistance; - XnActualRealProperty m_ZeroPlanePixelSize; - XnActualRealProperty m_EmitterDCmosDistance; - XnActualIntProperty m_NoDepthValue; - XnActualIntProperty m_ShadowValue; - - XnShiftToDepthStreamHelper m_S2DHelper; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEPTH_STREAM_H__ +#define __XN_DEPTH_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XN_DDK_CPP_API XnDepthStream : public XnPixelStream +{ +public: + XnDepthStream(const XnChar* csName, XnBool bAllowCustomResolutions, XnDepthPixel nDeviceMaxDepth, XnUInt16 nDeviceMaxShift); + ~XnDepthStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnDepthPixel GetMinDepth() const { return (XnDepthPixel)m_MinDepth.GetValue(); } + inline XnDepthPixel GetMaxDepth() const { return (XnDepthPixel)m_MaxDepth.GetValue(); } + inline XnUInt32 GetConstShift() const { return (XnUInt32)m_ConstShift.GetValue(); } + inline XnUInt32 GetPixelSizeFactor() const { return (XnUInt32)m_PixelSizeFactor.GetValue(); } + inline XnUInt16 GetMaxShift() const { return (XnUInt16)m_MaxShift.GetValue(); } + inline XnDepthPixel GetDeviceMaxDepth() const { return (XnDepthPixel)m_DeviceMaxDepth.GetValue(); } + inline XnUInt32 GetParamCoefficient() const { return (XnUInt32)m_ParamCoefficient.GetValue(); } + inline XnUInt32 GetShiftScale() const { return (XnUInt32)m_ShiftScale.GetValue(); } + inline XnDepthPixel GetZeroPlaneDistance() const { return (XnDepthPixel)m_ZeroPlaneDistance.GetValue(); } + inline XnDouble GetZeroPlanePixelSize() const { return m_ZeroPlanePixelSize.GetValue(); } + inline XnDouble GetEmitterDCmosDistance() const { return m_EmitterDCmosDistance.GetValue(); } + inline XnDepthPixel GetNoDepthValue() const { return (XnDepthPixel)m_NoDepthValue.GetValue(); } + inline XnDepthPixel GetShadowValue() const { return (XnDepthPixel)m_ShadowValue.GetValue(); } + + inline XnDepthPixel* GetShiftToDepthTable() const { return m_S2DHelper.GetShiftToDepthTable(); } + inline XnUInt16* GetDepthToShiftTable() const { return m_S2DHelper.GetDepthToShiftTable(); } + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& MinDepthProperty() { return m_MinDepth; } + inline XnActualIntProperty& MaxDepthProperty() { return m_MaxDepth; } + inline XnActualIntProperty& ConstShiftProperty() { return m_ConstShift; } + inline XnActualIntProperty& PixelSizeFactorProperty() { return m_PixelSizeFactor; } + inline XnActualIntProperty& MaxShiftProperty() { return m_MaxShift; } + inline XnActualIntProperty& DeviceMaxDepthProperty() { return m_DeviceMaxDepth; } + inline XnActualIntProperty& ParamCoefficientProperty() { return m_ParamCoefficient; } + inline XnActualIntProperty& ShiftScaleProperty() { return m_ShiftScale; } + inline XnActualIntProperty& ZeroPlaneDistanceProperty() { return m_ZeroPlaneDistance; } + inline XnActualRealProperty& ZeroPlanePixelSizeProperty() { return m_ZeroPlanePixelSize; } + inline XnActualRealProperty& EmitterDCmosDistanceProperty() { return m_EmitterDCmosDistance; } + inline XnActualIntProperty& NoDepthValueProperty() { return m_NoDepthValue; } + inline XnActualIntProperty& ShadowValueProperty() { return m_ShadowValue; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetMinDepth(XnDepthPixel nMinDepth); + virtual XnStatus SetMaxDepth(XnDepthPixel nMaxDepth); + +protected: + //--------------------------------------------------------------------------- + // Helper functions + //--------------------------------------------------------------------------- + XnStatus ValidateDepthValue(XnDepthPixel nDepth); + +private: + XnStatus OnOutputFormatChanged(); + + // callbacks + static XnStatus XN_CALLBACK_TYPE SetMinDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetMaxDepthCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE OutputFormatValueChangedCallback(const XnProperty* pSender, void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_MinDepth; + XnActualIntProperty m_MaxDepth; + XnActualIntProperty m_ConstShift; + XnActualIntProperty m_PixelSizeFactor; + XnActualIntProperty m_MaxShift; + XnActualIntProperty m_DeviceMaxDepth; + XnActualIntProperty m_ParamCoefficient; + XnActualIntProperty m_ShiftScale; + XnActualIntProperty m_ZeroPlaneDistance; + XnActualRealProperty m_ZeroPlanePixelSize; + XnActualRealProperty m_EmitterDCmosDistance; + XnActualIntProperty m_NoDepthValue; + XnActualIntProperty m_ShadowValue; + + XnShiftToDepthStreamHelper m_S2DHelper; +}; + #endif //__XN_DEPTH_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceBase.cpp b/Source/XnDDK/XnDeviceBase.cpp index 959ed6f..eeccbd6 100644 --- a/Source/XnDDK/XnDeviceBase.cpp +++ b/Source/XnDDK/XnDeviceBase.cpp @@ -1,1765 +1,1765 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceBase.h" -#include -#include -#include "XnIntProperty.h" -#include "XnRealProperty.h" -#include "XnStringProperty.h" -#include "XnGeneralProperty.h" -#include "XnPropertySetInternal.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DUMP_STREAMS_DATA "StreamsData" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnWaitForPrimaryData -{ - XnDeviceBase* pThis; - XnStreamDataSet* pSet; -} XnWaitForPrimaryData; - -typedef struct XnWaitForStreamData -{ - XnDeviceBase* pThis; - XnDeviceStream* pStream; -} XnWaitForStreamData; - -typedef struct XnPropertyCallback -{ - XnPropertyCallback(XnDeviceHandle DeviceHandle, const XnChar* strModule, const XnChar* strProp, XnDeviceOnPropertyChangedEventHandler pHandler, void* pCookie) : - DeviceHandle(DeviceHandle), - pHandler(pHandler), - pCookie(pCookie) - { - strcpy(this->strModule, strModule); - strcpy(this->strProp, strProp); - } - - XnDeviceHandle DeviceHandle; - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnDeviceOnPropertyChangedEventHandler pHandler; - void* pCookie; - XnCallbackHandle hCallback; - -} XnPropertyCallback; - -//--------------------------------------------------------------------------- -// Public Methods -//--------------------------------------------------------------------------- -XnDeviceBase::XnDeviceBase(const XnChar* csName, XnBool bStrictProperties) : - m_bStrictProperties(bStrictProperties), - m_pDevicePropertiesHolder(NULL), - m_DeviceName(XN_MODULE_PROPERTY_DEVICE_NAME, csName), - m_ReadWriteMode(XN_MODULE_PROPERTY_READ_WRITE_MODE, XN_DEVICE_MODE_READ), - m_PrimaryStream(XN_MODULE_PROPERTY_PRIMARY_STREAM, XN_PRIMARY_STREAM_ANY), - m_DeviceMirror(XN_MODULE_PROPERTY_MIRROR, FALSE), - m_HighResTimestamps(XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, TRUE), - m_SDKVersionProp(XN_MODULE_PROPERTY_SDK_VERSION, &m_SDKVersion, sizeof(XnSDKVersion)), - m_SharingMode(XN_MODULE_PROPERTY_SHARE_MODE, XN_DEVICE_EXCLUSIVE), - m_hNewDataEvent(NULL), - m_nLastReadTimestamp(0), - m_nLastReadFrameID(0), - m_nLastTimestamp(0), - m_nLastFrameID(0), - m_StreamsDataDump(XN_DUMP_CLOSED) -{ - // update set callbacks - m_PrimaryStream.UpdateSetCallback(SetPrimaryStreamCallback, this); - m_DeviceMirror.UpdateSetCallback(SetMirrorCallback, this); - m_HighResTimestamps.UpdateSetCallback(SetHighresTimestampsCallback, this); - - m_SDKVersion.nMajor = XN_PS_MAJOR_VERSION; - m_SDKVersion.nMinor = XN_PS_MINOR_VERSION; - m_SDKVersion.nMaintenance = XN_PS_MAINTENANCE_VERSION; - m_SDKVersion.nBuild = XN_PS_BUILD_VERSION; -} - -XnDeviceBase::~XnDeviceBase() -{ -} - -XnStatus XnDeviceBase::Init(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first init the device - nRetVal = InitImpl(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - // and now create streams - if (pDeviceConfig->pInitialValues != NULL) - { - nRetVal = CreateStreams(pDeviceConfig->pInitialValues); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::InitImpl(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pDeviceConfig); - - // create device module - nRetVal = CreateDeviceModule(&m_pDevicePropertiesHolder); - XN_IS_STATUS_OK(nRetVal); - - // check if we have initial values for device modules - XnActualPropertiesHash* pDeviceModuleInitialProps = NULL; - if (pDeviceConfig->pInitialValues != NULL) - { - pDeviceConfig->pInitialValues->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModuleInitialProps); - } - - // init device module - nRetVal = m_pDevicePropertiesHolder->Init(pDeviceModuleInitialProps); - XN_IS_STATUS_OK(nRetVal); - - // set read/write mode (we need to do it AFTER module init to override original value) - nRetVal = m_ReadWriteMode.UnsafeUpdateValue(pDeviceConfig->DeviceMode); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_SharingMode.UnsafeUpdateValue(pDeviceConfig->SharingMode); - XN_IS_STATUS_OK(nRetVal); - - // add the device module - nRetVal = AddModule(m_pDevicePropertiesHolder); - XN_IS_STATUS_OK(nRetVal); - - // create the new data event - nRetVal = xnOSCreateEvent(&m_hNewDataEvent, FALSE); - XN_IS_STATUS_OK(nRetVal); - - // init dump - xnDumpInit(&m_StreamsDataDump, XN_DUMP_STREAMS_DATA, "", "%s.csv", XN_DUMP_STREAMS_DATA); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // free all modules - while (m_Modules.Size() != 0) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)m_Modules.begin().Value(); - if (IsStream(pModuleHolder->GetModule())) - { - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - strcpy(strName, pModuleHolder->GetModule()->GetName()); - nRetVal = DestroyStream(strName); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // free memory of registered properties to this module - FreeModuleRegisteredProperties(m_Modules.begin().Key()); - - pModuleHolder->GetModule()->Free(); - DestroyModule(pModuleHolder); - m_Modules.Remove(m_Modules.begin()); - } - } - - m_pDevicePropertiesHolder = NULL; - - m_Modules.Clear(); - - // close event - xnOSCloseEvent(&m_hNewDataEvent); - - // close dump - xnDumpClose(&m_StreamsDataDump); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CreateModule(const XnChar* strName, XnDeviceModuleHolder** ppModuleHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - XnDeviceModule* pModule; - XnDeviceModuleHolder* pHolder; - - // create module - XN_VALIDATE_NEW(pModule, XnDeviceModule, strName); - - // create holder - pHolder = XN_NEW(XnDeviceModuleHolder, pModule, !m_bStrictProperties); - if (pHolder == NULL) - { - XN_DELETE(pModule); - return XN_STATUS_ALLOC_FAILED; - } - - *ppModuleHolder = pHolder; - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create module - nRetVal = CreateModule(XN_MODULE_NAME_DEVICE, ppModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); - - // add device properties - XnProperty* pProps[] = { &m_ReadWriteMode, &m_SharingMode, &m_PrimaryStream, &m_DeviceMirror, - &m_SDKVersionProp, &m_HighResTimestamps, &m_DeviceName }; - - nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(*ppModuleHolder); - *ppModuleHolder = NULL; - return (nRetVal); - } - - return XN_STATUS_OK; -} - -void XnDeviceBase::DestroyModule(XnDeviceModuleHolder* pModuleHolder) -{ - XN_DELETE(pModuleHolder->GetModule()); - XN_DELETE(pModuleHolder); -} - -XnStatus XnDeviceBase::SetPrimaryStream(const XnChar* strPrimaryStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (strcmp(strPrimaryStream, XN_PRIMARY_STREAM_ANY) != 0 && - strcmp(strPrimaryStream, XN_PRIMARY_STREAM_NONE) != 0) - { - // specific stream. check it exists - XnDeviceStream* pStream; - nRetVal = FindStream(strPrimaryStream, &pStream); - if (nRetVal != XN_STATUS_OK) - { - return XN_STATUS_UNSUPPORTED_STREAM; - } - } - - // OK. set the value - nRetVal = m_PrimaryStream.UnsafeUpdateValue(strPrimaryStream); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetMirror(XnBool bMirror) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // change all streams - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); - nRetVal = pStream->SetMirror(bMirror); - XN_IS_STATUS_OK(nRetVal); - } - } - - // and set property - nRetVal = m_DeviceMirror.UnsafeUpdateValue(bMirror); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetHighresTimestamps(XnBool bHighRes) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_HighResTimestamps.UnsafeUpdateValue(bHighRes); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OUTPUT_PTR(pnStreamNamesCount); - // NOTE: we allow aStreamName to be NULL - - // first of all count streams - XnUInt32 nStreamsCount = m_SupportedStreams.Size(); - - // now check if we have enough room - if (nStreamsCount > *pnStreamNamesCount) - { - *pnStreamNamesCount = nStreamsCount; - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - // now copy values - nStreamsCount = 0; - for (XnStringsHash::Iterator it = m_SupportedStreams.begin(); it != m_SupportedStreams.end(); ++it) - { - aStreamNames[nStreamsCount] = it.Key(); - nStreamsCount++; - } - - *pnStreamNamesCount = nStreamsCount; - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::OpenStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(StreamName); - - xnLogVerbose(XN_MASK_DDK, "Opening stream %s...", StreamName); - - // find this stream - XnDeviceStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - // open it - nRetVal = pStream->Open(); - XN_IS_STATUS_OK(nRetVal); - - xnLogInfo(XN_MASK_DDK, "Stream %s is open.", StreamName); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::CloseStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(StreamName); - - xnLogVerbose(XN_MASK_DDK, "Closing stream %s...", StreamName); - - // find this stream - XnDeviceStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - // close it - nRetVal = pStream->Close(); - XN_IS_STATUS_OK(nRetVal); - - xnLogInfo(XN_MASK_DDK, "Stream %s is closed.", StreamName); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::OpenAllStreams() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_DDK, "Opening all streams..."); - - // go over modules list, and look for closed streams - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); - if (!pStream->IsOpen()) - { - nRetVal = pStream->Open(); - XN_IS_STATUS_OK(nRetVal); - } - } - } - - xnLogInfo(XN_MASK_DDK, "All streams are open."); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CloseAllStreams() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_DDK, "Closing all streams..."); - - // go over modules list, and look for closed streams - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - const XnChar* Name = it.Key(); - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); - if (pStream->IsOpen()) - { - nRetVal = pStream->Close(); - XN_IS_STATUS_OK(nRetVal); - } - } - } - - xnLogInfo(XN_MASK_DDK, "All streams are closed."); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first we need to count them - XnUInt32 nCount = 0; - - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - nCount++; - } - } - - if (nCount > *pnNamesCount) - { - *pnNamesCount = nCount; - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - // OK. we have enough space. Copy into it - nCount = 0; - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - pstrNames[nCount] = it.Key(); - nCount++; - } - } - - *pnNamesCount = nCount; - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(ModuleName); - XN_VALIDATE_OUTPUT_PTR(pbDoesExist); - - *pbDoesExist = FALSE; - - XnDeviceModuleHolder* pModuleHolder; - nRetVal = FindModule(ModuleName, &pModuleHolder); - if (nRetVal == XN_STATUS_OK) - { - *pbDoesExist = TRUE; - } - else if (nRetVal != XN_STATUS_DEVICE_MODULE_NOT_FOUND) - { - return nRetVal; - } - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XN_VALIDATE_INPUT_PTR(Handler); - - return m_OnStreamsChangeEvent.Register((StreamCollectionChangedEvent::HandlerPtr)Handler, pCookie, phCallback); -} - -XnStatus XnDeviceBase::UnregisterFromStreamsChange(XnCallbackHandle hCallback) -{ - XN_VALIDATE_INPUT_PTR(hCallback); - - return m_OnStreamsChangeEvent.Unregister(hCallback); -} - -XnStatus XnDeviceBase::CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(StreamName); - XN_VALIDATE_OUTPUT_PTR(ppStreamData); - - // find stream - XnDeviceStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - // and create stream output - nRetVal = pStream->CreateStreamData(ppStreamData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::DestroyStreamData(XnStreamData** ppStreamData) -{ - XN_VALIDATE_INPUT_PTR(ppStreamData); - - return XnStreamDataDestroy(ppStreamData); -} - -XnStatus XnDeviceBase::RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XN_VALIDATE_INPUT_PTR(Handler); - - return m_OnNewStreamDataEvent.Register(Handler, pCookie, phCallback); -} - -XnStatus XnDeviceBase::UnregisterFromNewStreamData(XnCallbackHandle hCallback) -{ - XN_VALIDATE_INPUT_PTR(hCallback); - - return m_OnNewStreamDataEvent.Unregister(hCallback); -} - -XnStatus XnDeviceBase::IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(StreamName); - XN_VALIDATE_OUTPUT_PTR(pbNewDataAvailable); - - *pbNewDataAvailable = FALSE; - - if (strcmp(StreamName, XN_PRIMARY_STREAM_ANY) == 0) - { - const XnChar* aStreamNames[100]; - XnUInt32 nCount = 100; - - nRetVal = GetStreamNames(aStreamNames, &nCount); - XN_IS_STATUS_OK(nRetVal); - - for (XnUInt32 i = 0; i < nCount; ++i) - { - // find stream - XnDeviceStream* pStream = NULL; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - if (pStream->IsNewDataAvailable()) - { - *pbNewDataAvailable = TRUE; - *pnTimestamp = pStream->GetLastTimestamp(); - break; - } - } - } - else - { - // find stream - XnDeviceStream* pStream = NULL; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - if (pStream->IsNewDataAvailable()) - { - *pbNewDataAvailable = TRUE; - *pnTimestamp = pStream->GetLastTimestamp(); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read - nRetVal = pStream->Read(pStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pStreamData->bIsNew) - { - if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) == 0 || - strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) - { - // when primary stream is any, any stream read makes the device advance - m_nLastReadTimestamp = XN_MAX(pStreamData->nTimestamp, m_nLastReadTimestamp); - m_nLastReadFrameID = XN_MAX(pStreamData->nFrameID, m_nLastReadFrameID); - } - else if (strcmp(m_PrimaryStream.GetValue(), pStream->GetName()) == 0) - { - // this is the primary stream - m_nLastReadTimestamp = pStreamData->nTimestamp; - m_nLastReadFrameID = pStreamData->nFrameID; - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::ReadStream(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_WRITE) - { - return XN_STATUS_IO_DEVICE_WRONG_MODE; - } - - // take the stream to read - XnDeviceStream* pStream; - nRetVal = FindStream(pStreamOutput->StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - // make sure it is open - if (!pStream->IsNewDataAvailable() && !pStream->IsOpen()) - { - return XN_STATUS_STREAM_NOT_OPEN; - } - - // wait for it to advance - nRetVal = WaitForStream(m_hNewDataEvent, pStream); - XN_IS_STATUS_OK(nRetVal); - - // and read - nRetVal = ReadFromStreamImpl(pStream, pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::Read(XnStreamDataSet* pStreamOutputSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - - if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_WRITE) - { - return XN_STATUS_IO_DEVICE_WRONG_MODE; - } - - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - xnDumpWriteString(m_StreamsDataDump, "%llu,Read Called\n", nNow); - - // First thing to do is wait for primary stream to advance. We do this BEFORE checking streams - // because device streams might change during this wait. - nRetVal = WaitForPrimaryStream(m_hNewDataEvent, pStreamOutputSet); - XN_IS_STATUS_OK(nRetVal); - - xnOSGetHighResTimeStamp(&nNow); - xnDumpWriteString(m_StreamsDataDump, "%llu,Read Condition Met\n", nNow); - - // take the list of stream output objects - XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nOutputsCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - - nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, apStreamOutputs, &nOutputsCount); - XN_IS_STATUS_OK(nRetVal); - - // now read - for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) - { - // find its corresponding stream - XnDeviceStream* pStream; - nRetVal = FindStream(apStreamOutputs[nIndex]->StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReadFromStreamImpl(pStream, apStreamOutputs[nIndex]); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::WriteStream(XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamData); - - if (m_ReadWriteMode.GetValue() != XN_DEVICE_MODE_WRITE) - { - return XN_STATUS_IO_DEVICE_WRONG_MODE; - } - - // take the stream to write - XnDeviceStream* pStream; - nRetVal = FindStream(pStreamData->StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - // make sure it is open - if (!pStream->IsOpen()) - { - return XN_STATUS_STREAM_NOT_OPEN; - } - - // and write - nRetVal = pStream->Write(pStreamData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::Write(XnStreamDataSet* pStreamDataSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamDataSet); - - if (m_ReadWriteMode.GetValue() != XN_DEVICE_MODE_WRITE) - { - return XN_STATUS_IO_DEVICE_WRONG_MODE; - } - - // take the list of stream output objects - XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nOutputsCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - - nRetVal = XnStreamDataSetCopyToArray(pStreamDataSet, apStreamOutputs, &nOutputsCount); - XN_IS_STATUS_OK(nRetVal); - - // find the stream for each one - XnDeviceStream* apStreams[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - - for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) - { - // find its corresponding stream - nRetVal = FindStream(apStreamOutputs[nIndex]->StreamName, &apStreams[nIndex]); - XN_IS_STATUS_OK(nRetVal); - - // make sure it is open - if (!apStreams[nIndex]->IsOpen()) - { - return XN_STATUS_STREAM_NOT_OPEN; - } - } - - // go over them, and write into each one - for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) - { - nRetVal = apStreams[nIndex]->Write(apStreamOutputs[nIndex]); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::Tell(XnUInt64* pnTimestamp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OUTPUT_PTR(pnTimestamp); - - *pnTimestamp = m_nLastTimestamp; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::TellFrame(XnUInt32* pnFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OUTPUT_PTR(pnFrameID); - - *pnFrameID = m_nLastFrameID; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) -{ - XnStatus nRetVal = XN_STATUS_OK; - - *pbDoesExist = FALSE; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - if (nRetVal == XN_STATUS_DEVICE_MODULE_NOT_FOUND) - { - return XN_STATUS_OK; - } - else - { - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = pModule->DoesPropertyExist(PropertyName, pbDoesExist); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetPropertyType(PropertyName, pnType); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->SetProperty(PropertyName, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->SetProperty(PropertyName, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->SetProperty(PropertyName, csValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->SetProperty(PropertyName, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetProperty(PropertyName, pnValue); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetProperty(PropertyName, pdValue); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetProperty(PropertyName, csValue); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetProperty(PropertyName, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CreateStreamsFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // go through numbers until no stream is found - XnUInt32 nStreamIndex = 0; - XnChar csKeyName[XN_INI_MAX_LEN]; - - while (TRUE) - { - sprintf(csKeyName, "Stream%d_Type", nStreamIndex); - - XnChar csStreamType[XN_INI_MAX_LEN]; - XnChar csStreamName[XN_INI_MAX_LEN]; - - nRetVal = xnOSReadStringFromINI(csINIFilePath, csSectionName, csKeyName, csStreamType, XN_INI_MAX_LEN); - if (nRetVal != XN_STATUS_OK) // no more streams - { - break; - } - - // check if the stream has a name - sprintf(csKeyName, "Stream%d_Name", nStreamIndex); - nRetVal = xnOSReadStringFromINI(csINIFilePath, csSectionName, csKeyName, csStreamName, XN_INI_MAX_LEN); - if (nRetVal != XN_STATUS_OK) - { - // use its type as a name - strcpy(csStreamName, csStreamType); - } - - nRetVal = CreateStream(csStreamType, csStreamName); - XN_IS_STATUS_OK(nRetVal); - - nStreamIndex++; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = DeviceModule()->LoadConfigFromFile(csINIFilePath, csSectionName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::StartTransaction() -{ - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CommitTransaction() -{ - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::RollbackTransaction() -{ - return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; -} - -#define XN_CHECK_RC_ROLLBACK(rc) \ - if (rc != XN_STATUS_OK) \ - { \ - RollbackTransaction(); \ - return (rc); \ - } - -XnStatus XnDeviceBase::BatchConfig(const XnPropertySet* pChangeSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pChangeSet); - - // start a transaction - nRetVal = StartTransaction(); - XN_IS_STATUS_OK(nRetVal); - - for (XnPropertySetData::ConstIterator itModule = pChangeSet->pData->begin(); itModule != pChangeSet->pData->end(); ++itModule) - { - // find this module - XnDeviceModule* pModule = NULL; - nRetVal = FindModule(itModule.Key(), &pModule); - XN_CHECK_RC_ROLLBACK(nRetVal); - - nRetVal = pModule->BatchConfig(*itModule.Value()); - XN_CHECK_RC_ROLLBACK(nRetVal); - } - - nRetVal = CommitTransaction(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - - // clear the set - nRetVal = XnPropertySetClear(pSet); - XN_IS_STATUS_OK(nRetVal); - - if (strModule != NULL) - { - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->GetAllProperties(pSet); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // enumerate over modules - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - - if (bNoStreams && IsStream(pModuleHolder->GetModule())) - continue; - - nRetVal = pModuleHolder->GetModule()->GetAllProperties(pSet); - XN_IS_STATUS_OK(nRetVal); - } - } - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(Module, &pModule); - XN_IS_STATUS_OK(nRetVal); - - XnPropertyCallback* pRealCookie; - XN_VALIDATE_NEW(pRealCookie, XnPropertyCallback, GetDeviceHandle(), Module, PropertyName, Handler, pCookie); - - // register - nRetVal = pModule->RegisterForOnPropertyValueChanged(PropertyName, PropertyValueChangedCallback, pRealCookie, &pRealCookie->hCallback); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pRealCookie); - return (nRetVal); - } - - m_PropertyCallbacks.AddLast(pRealCookie); - - *phCallback = pRealCookie; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(Module); - XN_VALIDATE_INPUT_PTR(PropertyName); - XN_VALIDATE_INPUT_PTR(hCallback); - - XnPropertyCallback* pRealCookie = (XnPropertyCallback*)hCallback; - - XnDeviceModule* pModule; - nRetVal = FindModule(Module, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // first unregister it from property - nRetVal = pModule->UnregisterFromOnPropertyValueChanged(PropertyName, pRealCookie->hCallback); - XN_IS_STATUS_OK(nRetVal); - - XnValue val = pRealCookie; - XnList::Iterator it = m_PropertyCallbacks.Find(val); - if (it != m_PropertyCallbacks.end()) - { - m_PropertyCallbacks.Remove(it); - } - - // now free the memory - XN_DELETE(pRealCookie); - - return (XN_STATUS_OK); -} - -//--------------------------------------------------------------------------- -// Protected Helper Methods -//--------------------------------------------------------------------------- - -XnStatus XnDeviceBase::AddModule(XnDeviceModuleHolder* pModuleHolder) -{ - XnDeviceModule* pModule = pModuleHolder->GetModule(); - - // make sure module doesn't exist yet - XnStringsHash::Iterator it = m_Modules.end(); - if (XN_STATUS_OK == m_Modules.Find(pModule->GetName(), it)) - { - xnLogError(XN_MASK_DEVICE, "A module with the name %s already exists!", pModule->GetName()); - return XN_STATUS_ERROR; - } - - // add it to the list - XnStatus nRetVal = m_Modules.Set(pModule->GetName(), pModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::RemoveModule(const XnChar* ModuleName) -{ - // remove it - XnValue props; - XnStatus nRetVal = m_Modules.Remove(ModuleName, props); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::FindModule(const XnChar* ModuleName, XnDeviceModule** ppModule) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModuleHolder* pHolder; - nRetVal = FindModule(ModuleName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - *ppModule = pHolder->GetModule(); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::FindModule(const XnChar* ModuleName, XnDeviceModuleHolder** ppModuleHolder) -{ - XnStringsHash::Iterator it = m_Modules.end(); - XnStatus nRetVal = m_Modules.Find(ModuleName, it); - if (nRetVal == XN_STATUS_NO_MATCH) - { - return (XN_STATUS_DEVICE_MODULE_NOT_FOUND); - } - XN_IS_STATUS_OK(nRetVal); - - *ppModuleHolder = (XnDeviceModuleHolder*)it.Value(); - - return XN_STATUS_OK; -} - -XnBool XnDeviceBase::IsStream(XnDeviceModule* pModule) -{ - XnProperty* pProperty; - XnStatus nRetVal = pModule->GetProperty(XN_STREAM_PROPERTY_IS_STREAM, &pProperty); - if (nRetVal != XN_STATUS_OK) - return FALSE; - - if (pProperty->GetType() != XN_PROPERTY_TYPE_INTEGER) - return FALSE; - - XnIntProperty* pIntProperty = (XnIntProperty*)pProperty; - - XnUInt64 nValue; - nRetVal = pIntProperty->GetValue(&nValue); - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_DDK, "Failed getting the value of the IsStream property: %s", xnGetStatusString(nRetVal)); - return FALSE; - } - - return (XnBool)nValue; -} - -XnStatus XnDeviceBase::FindStream(const XnChar* StreamName, XnDeviceStream** ppStream) -{ - // find the module - XnDeviceModuleHolder* pStreamHolder = NULL; - XnStatus nRetVal = FindStream(StreamName, &pStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - *ppStream = (XnDeviceStream*)pStreamHolder->GetModule(); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::FindStream(const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - // find the module - XnDeviceModuleHolder* pModuleHolder = NULL; - XnStatus nRetVal = FindModule(StreamName, &pModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - // check if this is a stream - if (!IsStream(pModuleHolder->GetModule())) - return XN_STATUS_MODULE_IS_NOT_STREAM; - - *ppStreamHolder = pModuleHolder; - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::AddSupportedStream(const XnChar* StreamType) -{ - // make sure stream doesn't exist yet - XnStringsHash::Iterator it = m_SupportedStreams.end(); - if (XN_STATUS_OK == m_SupportedStreams.Find(StreamType, it)) - { - xnLogError(XN_MASK_DEVICE, "A stream with the name %s already exists!", StreamType); - return XN_STATUS_STREAM_ALREADY_EXISTS; - } - - // add it to the list - XnStatus nRetVal = m_SupportedStreams.Set(StreamType, NULL); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetStreamRequiredDataSize(const XnChar* StreamName, XnUInt32* pnRequiredSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find stream - XnDeviceStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - *pnRequiredSize = pStream->GetRequiredDataSize(); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::CreateStreams(const XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnPropertySetData::ConstIterator it = pSet->pData->begin(); it != pSet->pData->end(); ++it) - { - // check if this module is a stream - XnActualPropertiesHash* pModule = it.Value(); - - XnActualPropertiesHash::ConstIterator itProp = pModule->end(); - if (XN_STATUS_OK == pModule->Find(XN_STREAM_PROPERTY_TYPE, itProp)) - { - // create a copy of the properties - XnActualPropertiesHash streamProps(it.Key()); - nRetVal = streamProps.CopyFrom(*pModule); - XN_IS_STATUS_OK(nRetVal); - - // remove the type property - nRetVal = streamProps.Remove(XN_STREAM_PROPERTY_TYPE); - XN_IS_STATUS_OK(nRetVal); - - // and create the stream - XnActualStringProperty* pActualProp = (XnActualStringProperty*)itProp.Value(); - nRetVal = CreateStreamImpl(pActualProp->GetValue(), it.Key(), &streamProps); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::ValidateOnlyModule(const XnPropertySet* pSet, const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnPropertySetData::ConstIterator it = pSet->pData->begin(); - if (it == pSet->pData->end()) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set did not contain any stream!"); - } - - if (strcmp(it.Key(), StreamName) != 0) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set module name does not match stream name!"); - } - - if (++it != pSet->pData->end()) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set contains more than one module!"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check for name - if (StreamName == NULL) - StreamName = StreamType; - - XnActualPropertiesHash* pInitialValuesHash = NULL; - - if (pInitialValues != NULL) - { - // validate property set - nRetVal = ValidateOnlyModule(pInitialValues, StreamName); - XN_IS_STATUS_OK(nRetVal); - - pInitialValuesHash = pInitialValues->pData->begin().Value(); - } - - nRetVal = CreateStreamImpl(StreamType, StreamName, pInitialValuesHash); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogInfo(XN_MASK_DDK, "Creating stream '%s' of type '%s'...", strName, strType); - - XnDeviceModule* pModule; - if (FindModule(strName, &pModule) == XN_STATUS_OK) - { - // already exists. check sharing mode (when shared, we allow "creating" the same stream) - if (GetSharingMode() != XN_DEVICE_SHARED || - !IsStream(pModule) || - strcmp(strType, ((XnDeviceStream*)pModule)->GetType()) != 0) - { - XN_LOG_WARNING_RETURN(XN_STATUS_STREAM_ALREADY_EXISTS, XN_MASK_DDK, "A stream with this name already exists!"); - } - - // OK, we'll allow this. Just set new configuration - if (pInitialSet != NULL) - { - nRetVal = pModule->BatchConfig(*pInitialSet); - XN_IS_STATUS_OK(nRetVal); - } - } - else - { - // create stream - XnDeviceModuleHolder* pNewStreamHolder = NULL; - - nRetVal = CreateStreamModule(strType, strName, &pNewStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - XnDeviceStream* pNewStream = (XnDeviceStream*)(pNewStreamHolder->GetModule()); - if (pNewStream == NULL) - { - DestroyStreamModule(pNewStreamHolder); - XN_LOG_ERROR_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Internal Error: Invalid new stream!"); - } - - // initialize the stream - xnLogVerbose(XN_MASK_DDK, "Initializing stream '%s'...", strName); - - nRetVal = pNewStreamHolder->Init(pInitialSet); - if (nRetVal != XN_STATUS_OK) - { - DestroyStreamModule(pNewStreamHolder); - return (nRetVal); - } - - // set it's mirror value (if not requested otherwise) - XnBool bSetMirror = TRUE; - - if (pInitialSet != NULL) - { - XnActualPropertiesHash::ConstIterator it = pInitialSet->end(); - if (XN_STATUS_OK == pInitialSet->Find(XN_MODULE_PROPERTY_MIRROR, it)) - { - bSetMirror = FALSE; - } - } - - if (bSetMirror) - { - nRetVal = pNewStream->SetMirror((XnBool)m_DeviceMirror.GetValue()); - if (nRetVal != XN_STATUS_OK) - { - DestroyStreamModule(pNewStreamHolder); - return (nRetVal); - } - } - - // add it to the list of existing modules - nRetVal = AddModule(pNewStreamHolder); - if (nRetVal != XN_STATUS_OK) - { - DestroyStreamModule(pNewStreamHolder); - return (nRetVal); - } - - xnLogInfo(XN_MASK_DDK, "Stream '%s' was initialized.", strName); - - nRetVal = StreamAdded(pNewStream); - XN_IS_STATUS_OK(nRetVal); - - xnLogInfo(XN_MASK_DDK, "'%s' stream was created.", strName); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::StreamAdded(XnDeviceStream* pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // register to the NewData event - if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_READ) - { - pStream->SetNewDataCallback(NewStreamDataCallback, this); - } - - // raise the change event - m_OnStreamsChangeEvent.Raise(GetDeviceHandle(), pStream->GetName(), XN_DEVICE_STREAM_ADDED); - - return (XN_STATUS_OK); -} - -void XnDeviceBase::FreeModuleRegisteredProperties(const XnChar* strModule) -{ - // free memory of registered properties to this stream - XnList::Iterator it = m_PropertyCallbacks.begin(); - while (it != m_PropertyCallbacks.end()) - { - XnList::Iterator cur = it; - it++; - - XnPropertyCallback* pRealCallback = (XnPropertyCallback*)*cur; - if (strcmp(pRealCallback->strModule, strModule) == 0) - { - m_PropertyCallbacks.Remove(cur); - XN_DELETE(pRealCallback); - } - } -} - -XnStatus XnDeviceBase::DestroyStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogInfo(XN_MASK_DDK, "Destroying stream '%s'...", StreamName); - - // keep the stream name (we now delete the module, so the name will be lost) - XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; - strncpy(strStreamName, StreamName, XN_DEVICE_MAX_STRING_LENGTH); - - // Find the stream - XnDeviceModuleHolder* pStreamHolder; - nRetVal = FindStream(strStreamName, &pStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - // remove it from map - nRetVal = RemoveModule(strStreamName); - XN_IS_STATUS_OK(nRetVal); - - // and free it's memory - DestroyStreamModule(pStreamHolder); - - // free memory of registered properties to this stream - FreeModuleRegisteredProperties(StreamName); - - // raise event - m_OnStreamsChangeEvent.Raise(GetDeviceHandle(), strStreamName, XN_DEVICE_STREAM_DELETED); - - xnLogVerbose(XN_MASK_DDK, "'%s' stream destroyed.", strStreamName); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolder** apModules, XnUInt32* pnCount) -{ - XnUInt32 nCount = 0; - - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - apModules[nCount] = (XnDeviceModuleHolder*)it.Value(); - nCount++; - } - - *pnCount = nCount; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolderList& list) -{ - XnStatus nRetVal = XN_STATUS_OK; - - list.Clear(); - - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - list.AddLast((XnDeviceModuleHolder*)it.Value()); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::GetStreamsList(XnDeviceModuleHolderList& list) -{ - XnStatus nRetVal = XN_STATUS_OK; - - list.Clear(); - - for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) - { - XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); - if (IsStream(pModuleHolder->GetModule())) - { - list.AddLast(pModuleHolder); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::RaiseNewStreamDataEvent(const XnChar* StreamName) -{ - m_OnNewStreamDataEvent.Raise(GetDeviceHandle(), StreamName); - - return XN_STATUS_OK; -} - -void XnDeviceBase::OnNewStreamData(XnDeviceStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID) -{ - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - xnDumpWriteString(m_StreamsDataDump, "%llu,%s,%llu,%u\n", nNow, pStream->GetName(), nTimestamp, nFrameID); - - if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) == 0 || - strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) - { - // any stream makes us advance - m_nLastTimestamp = XN_MAX(m_nLastTimestamp, nTimestamp); - m_nLastFrameID = XN_MAX(m_nLastFrameID, nFrameID); - } - else if (strcmp(m_PrimaryStream.GetValue(), pStream->GetName()) == 0) // this stream is the primary - { - m_nLastTimestamp = nTimestamp; - m_nLastFrameID = nFrameID; - } - - XnStatus nRetVal = xnOSSetEvent(m_hNewDataEvent); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_DDK, "Failed setting the new data event: %s", xnGetStatusString(nRetVal)); - } - - RaiseNewStreamDataEvent(pStream->GetName()); -} - -void XnDeviceBase::ResetLastTimestampAndFrame() -{ - m_nLastFrameID = 0; - m_nLastTimestamp = 0; - m_nLastReadFrameID = 0; - m_nLastReadTimestamp = 0; -} - -void XnDeviceBase::NewStreamDataCallback(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie) -{ - XnDeviceBase* pThis = (XnDeviceBase*)pCookie; - pThis->OnNewStreamData(pSender, nTimestamp, nFrameID); -} - -XnBool XnDeviceBase::HasPrimaryStreamAdvanced(XnStreamDataSet* pOutputSet) -{ - if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) - { - // special case of None: condition is always true - return TRUE; - } - - const XnChar* astrNames[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nArraySize = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - - // take a list of streams to check for new data - if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) != 0) - { - // we have a specific stream. Add it to the list - astrNames[0] = m_PrimaryStream.GetValue(); - nArraySize = 1; - } - else - { - // special case of ANY. we need to check every one of requested streams - XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - if (XN_STATUS_OK != XnStreamDataSetCopyToArray(pOutputSet, apStreamOutputs, &nArraySize)) - { - return FALSE; - } - - for (XnUInt32 i = 0; i < nArraySize; ++i) - { - astrNames[i] = apStreamOutputs[i]->StreamName; - } - } - - // now check if we have new data - for (XnUInt32 i = 0; i < nArraySize; ++i) - { - XnDeviceStream* pStream = NULL; - if (XN_STATUS_OK == FindStream(astrNames[i], &pStream)) - { - if (pStream->IsNewDataAvailable()) - return TRUE; - } - } - - return FALSE; -} - -XnBool XnDeviceBase::HasStreamAdvanced(XnDeviceStream* pStream) -{ - return pStream->IsNewDataAvailable(); -} - -XnBool XnDeviceBase::HasPrimaryStreamAdvancedCallback(void* pCookie) -{ - XnWaitForPrimaryData* pWaitData = (XnWaitForPrimaryData*)pCookie; - return pWaitData->pThis->HasPrimaryStreamAdvanced(pWaitData->pSet); -} - -XnBool XnDeviceBase::HasStreamAdvancedCallback(void* pCookie) -{ - XnWaitForStreamData* pWaitData = (XnWaitForStreamData*)pCookie; - return pWaitData->pThis->HasStreamAdvanced(pWaitData->pStream); -} - -XnStatus XnDeviceBase::WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnWaitForStreamData WaitData; - WaitData.pThis = this; - WaitData.pStream = pStream; - nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnDeviceBase::HasStreamAdvancedCallback, &WaitData); - if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) - { - xnLogError(XN_MASK_DDK, "Not responding - stream did not advance!"); - return (XN_STATUS_IO_DEVICE_NOT_RESPONDING); - } - else - { - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceBase::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnWaitForPrimaryData WaitData; - WaitData.pThis = this; - WaitData.pSet = pSet; - nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnDeviceBase::HasPrimaryStreamAdvancedCallback, &WaitData); - if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) - { - xnLogError(XN_MASK_DDK, "Not responding - primary stream did not advance!"); - return (XN_STATUS_IO_DEVICE_NOT_RESPONDING); - } - else - { - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceBase::PropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnPropertyCallback* pUserCallback = (XnPropertyCallback*)pCookie; - - // TODO: consider catching exceptions (if user does some stupid things) - pUserCallback->pHandler(pUserCallback->DeviceHandle, pUserCallback->strModule, pUserCallback->strProp, pUserCallback->pCookie); - - return XN_STATUS_OK; -} - -XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetPrimaryStreamCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie) -{ - XnDeviceBase* pThis = (XnDeviceBase*)pCookie; - return pThis->SetPrimaryStream(strValue); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceBase* pThis = (XnDeviceBase*)pCookie; - return pThis->SetMirror((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetHighresTimestampsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceBase* pThis = (XnDeviceBase*)pCookie; - return pThis->SetHighresTimestamps((XnBool)nValue); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceBase.h" +#include +#include +#include "XnIntProperty.h" +#include "XnRealProperty.h" +#include "XnStringProperty.h" +#include "XnGeneralProperty.h" +#include "XnPropertySetInternal.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DUMP_STREAMS_DATA "StreamsData" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnWaitForPrimaryData +{ + XnDeviceBase* pThis; + XnStreamDataSet* pSet; +} XnWaitForPrimaryData; + +typedef struct XnWaitForStreamData +{ + XnDeviceBase* pThis; + XnDeviceStream* pStream; +} XnWaitForStreamData; + +typedef struct XnPropertyCallback +{ + XnPropertyCallback(XnDeviceHandle DeviceHandle, const XnChar* strModule, const XnChar* strProp, XnDeviceOnPropertyChangedEventHandler pHandler, void* pCookie) : + DeviceHandle(DeviceHandle), + pHandler(pHandler), + pCookie(pCookie) + { + strcpy(this->strModule, strModule); + strcpy(this->strProp, strProp); + } + + XnDeviceHandle DeviceHandle; + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnDeviceOnPropertyChangedEventHandler pHandler; + void* pCookie; + XnCallbackHandle hCallback; + +} XnPropertyCallback; + +//--------------------------------------------------------------------------- +// Public Methods +//--------------------------------------------------------------------------- +XnDeviceBase::XnDeviceBase(const XnChar* csName, XnBool bStrictProperties) : + m_bStrictProperties(bStrictProperties), + m_pDevicePropertiesHolder(NULL), + m_DeviceName(XN_MODULE_PROPERTY_DEVICE_NAME, csName), + m_ReadWriteMode(XN_MODULE_PROPERTY_READ_WRITE_MODE, XN_DEVICE_MODE_READ), + m_PrimaryStream(XN_MODULE_PROPERTY_PRIMARY_STREAM, XN_PRIMARY_STREAM_ANY), + m_DeviceMirror(XN_MODULE_PROPERTY_MIRROR, FALSE), + m_HighResTimestamps(XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, TRUE), + m_SDKVersionProp(XN_MODULE_PROPERTY_SDK_VERSION, &m_SDKVersion, sizeof(XnSDKVersion)), + m_SharingMode(XN_MODULE_PROPERTY_SHARE_MODE, XN_DEVICE_EXCLUSIVE), + m_hNewDataEvent(NULL), + m_nLastReadTimestamp(0), + m_nLastReadFrameID(0), + m_nLastTimestamp(0), + m_nLastFrameID(0), + m_StreamsDataDump(XN_DUMP_CLOSED) +{ + // update set callbacks + m_PrimaryStream.UpdateSetCallback(SetPrimaryStreamCallback, this); + m_DeviceMirror.UpdateSetCallback(SetMirrorCallback, this); + m_HighResTimestamps.UpdateSetCallback(SetHighresTimestampsCallback, this); + + m_SDKVersion.nMajor = XN_PS_MAJOR_VERSION; + m_SDKVersion.nMinor = XN_PS_MINOR_VERSION; + m_SDKVersion.nMaintenance = XN_PS_MAINTENANCE_VERSION; + m_SDKVersion.nBuild = XN_PS_BUILD_VERSION; +} + +XnDeviceBase::~XnDeviceBase() +{ +} + +XnStatus XnDeviceBase::Init(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first init the device + nRetVal = InitImpl(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + // and now create streams + if (pDeviceConfig->pInitialValues != NULL) + { + nRetVal = CreateStreams(pDeviceConfig->pInitialValues); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::InitImpl(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pDeviceConfig); + + // create device module + nRetVal = CreateDeviceModule(&m_pDevicePropertiesHolder); + XN_IS_STATUS_OK(nRetVal); + + // check if we have initial values for device modules + XnActualPropertiesHash* pDeviceModuleInitialProps = NULL; + if (pDeviceConfig->pInitialValues != NULL) + { + pDeviceConfig->pInitialValues->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModuleInitialProps); + } + + // init device module + nRetVal = m_pDevicePropertiesHolder->Init(pDeviceModuleInitialProps); + XN_IS_STATUS_OK(nRetVal); + + // set read/write mode (we need to do it AFTER module init to override original value) + nRetVal = m_ReadWriteMode.UnsafeUpdateValue(pDeviceConfig->DeviceMode); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_SharingMode.UnsafeUpdateValue(pDeviceConfig->SharingMode); + XN_IS_STATUS_OK(nRetVal); + + // add the device module + nRetVal = AddModule(m_pDevicePropertiesHolder); + XN_IS_STATUS_OK(nRetVal); + + // create the new data event + nRetVal = xnOSCreateEvent(&m_hNewDataEvent, FALSE); + XN_IS_STATUS_OK(nRetVal); + + // init dump + xnDumpInit(&m_StreamsDataDump, XN_DUMP_STREAMS_DATA, "", "%s.csv", XN_DUMP_STREAMS_DATA); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // free all modules + while (m_Modules.Size() != 0) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)m_Modules.begin().Value(); + if (IsStream(pModuleHolder->GetModule())) + { + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + strcpy(strName, pModuleHolder->GetModule()->GetName()); + nRetVal = DestroyStream(strName); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // free memory of registered properties to this module + FreeModuleRegisteredProperties(m_Modules.begin().Key()); + + pModuleHolder->GetModule()->Free(); + DestroyModule(pModuleHolder); + m_Modules.Remove(m_Modules.begin()); + } + } + + m_pDevicePropertiesHolder = NULL; + + m_Modules.Clear(); + + // close event + xnOSCloseEvent(&m_hNewDataEvent); + + // close dump + xnDumpClose(&m_StreamsDataDump); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CreateModule(const XnChar* strName, XnDeviceModuleHolder** ppModuleHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + XnDeviceModule* pModule; + XnDeviceModuleHolder* pHolder; + + // create module + XN_VALIDATE_NEW(pModule, XnDeviceModule, strName); + + // create holder + pHolder = XN_NEW(XnDeviceModuleHolder, pModule, !m_bStrictProperties); + if (pHolder == NULL) + { + XN_DELETE(pModule); + return XN_STATUS_ALLOC_FAILED; + } + + *ppModuleHolder = pHolder; + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // create module + nRetVal = CreateModule(XN_MODULE_NAME_DEVICE, ppModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); + + // add device properties + XnProperty* pProps[] = { &m_ReadWriteMode, &m_SharingMode, &m_PrimaryStream, &m_DeviceMirror, + &m_SDKVersionProp, &m_HighResTimestamps, &m_DeviceName }; + + nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(*ppModuleHolder); + *ppModuleHolder = NULL; + return (nRetVal); + } + + return XN_STATUS_OK; +} + +void XnDeviceBase::DestroyModule(XnDeviceModuleHolder* pModuleHolder) +{ + XN_DELETE(pModuleHolder->GetModule()); + XN_DELETE(pModuleHolder); +} + +XnStatus XnDeviceBase::SetPrimaryStream(const XnChar* strPrimaryStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (strcmp(strPrimaryStream, XN_PRIMARY_STREAM_ANY) != 0 && + strcmp(strPrimaryStream, XN_PRIMARY_STREAM_NONE) != 0) + { + // specific stream. check it exists + XnDeviceStream* pStream; + nRetVal = FindStream(strPrimaryStream, &pStream); + if (nRetVal != XN_STATUS_OK) + { + return XN_STATUS_UNSUPPORTED_STREAM; + } + } + + // OK. set the value + nRetVal = m_PrimaryStream.UnsafeUpdateValue(strPrimaryStream); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetMirror(XnBool bMirror) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // change all streams + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); + nRetVal = pStream->SetMirror(bMirror); + XN_IS_STATUS_OK(nRetVal); + } + } + + // and set property + nRetVal = m_DeviceMirror.UnsafeUpdateValue(bMirror); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetHighresTimestamps(XnBool bHighRes) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_HighResTimestamps.UnsafeUpdateValue(bHighRes); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OUTPUT_PTR(pnStreamNamesCount); + // NOTE: we allow aStreamName to be NULL + + // first of all count streams + XnUInt32 nStreamsCount = m_SupportedStreams.Size(); + + // now check if we have enough room + if (nStreamsCount > *pnStreamNamesCount) + { + *pnStreamNamesCount = nStreamsCount; + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + // now copy values + nStreamsCount = 0; + for (XnStringsHash::Iterator it = m_SupportedStreams.begin(); it != m_SupportedStreams.end(); ++it) + { + aStreamNames[nStreamsCount] = it.Key(); + nStreamsCount++; + } + + *pnStreamNamesCount = nStreamsCount; + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::OpenStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(StreamName); + + xnLogVerbose(XN_MASK_DDK, "Opening stream %s...", StreamName); + + // find this stream + XnDeviceStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + // open it + nRetVal = pStream->Open(); + XN_IS_STATUS_OK(nRetVal); + + xnLogInfo(XN_MASK_DDK, "Stream %s is open.", StreamName); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::CloseStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(StreamName); + + xnLogVerbose(XN_MASK_DDK, "Closing stream %s...", StreamName); + + // find this stream + XnDeviceStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + // close it + nRetVal = pStream->Close(); + XN_IS_STATUS_OK(nRetVal); + + xnLogInfo(XN_MASK_DDK, "Stream %s is closed.", StreamName); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::OpenAllStreams() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_DDK, "Opening all streams..."); + + // go over modules list, and look for closed streams + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); + if (!pStream->IsOpen()) + { + nRetVal = pStream->Open(); + XN_IS_STATUS_OK(nRetVal); + } + } + } + + xnLogInfo(XN_MASK_DDK, "All streams are open."); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CloseAllStreams() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_DDK, "Closing all streams..."); + + // go over modules list, and look for closed streams + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + const XnChar* Name = it.Key(); + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule(); + if (pStream->IsOpen()) + { + nRetVal = pStream->Close(); + XN_IS_STATUS_OK(nRetVal); + } + } + } + + xnLogInfo(XN_MASK_DDK, "All streams are closed."); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first we need to count them + XnUInt32 nCount = 0; + + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + nCount++; + } + } + + if (nCount > *pnNamesCount) + { + *pnNamesCount = nCount; + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + // OK. we have enough space. Copy into it + nCount = 0; + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + pstrNames[nCount] = it.Key(); + nCount++; + } + } + + *pnNamesCount = nCount; + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(ModuleName); + XN_VALIDATE_OUTPUT_PTR(pbDoesExist); + + *pbDoesExist = FALSE; + + XnDeviceModuleHolder* pModuleHolder; + nRetVal = FindModule(ModuleName, &pModuleHolder); + if (nRetVal == XN_STATUS_OK) + { + *pbDoesExist = TRUE; + } + else if (nRetVal != XN_STATUS_DEVICE_MODULE_NOT_FOUND) + { + return nRetVal; + } + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XN_VALIDATE_INPUT_PTR(Handler); + + return m_OnStreamsChangeEvent.Register((StreamCollectionChangedEvent::HandlerPtr)Handler, pCookie, phCallback); +} + +XnStatus XnDeviceBase::UnregisterFromStreamsChange(XnCallbackHandle hCallback) +{ + XN_VALIDATE_INPUT_PTR(hCallback); + + return m_OnStreamsChangeEvent.Unregister(hCallback); +} + +XnStatus XnDeviceBase::CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(StreamName); + XN_VALIDATE_OUTPUT_PTR(ppStreamData); + + // find stream + XnDeviceStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + // and create stream output + nRetVal = pStream->CreateStreamData(ppStreamData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::DestroyStreamData(XnStreamData** ppStreamData) +{ + XN_VALIDATE_INPUT_PTR(ppStreamData); + + return XnStreamDataDestroy(ppStreamData); +} + +XnStatus XnDeviceBase::RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XN_VALIDATE_INPUT_PTR(Handler); + + return m_OnNewStreamDataEvent.Register(Handler, pCookie, phCallback); +} + +XnStatus XnDeviceBase::UnregisterFromNewStreamData(XnCallbackHandle hCallback) +{ + XN_VALIDATE_INPUT_PTR(hCallback); + + return m_OnNewStreamDataEvent.Unregister(hCallback); +} + +XnStatus XnDeviceBase::IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(StreamName); + XN_VALIDATE_OUTPUT_PTR(pbNewDataAvailable); + + *pbNewDataAvailable = FALSE; + + if (strcmp(StreamName, XN_PRIMARY_STREAM_ANY) == 0) + { + const XnChar* aStreamNames[100]; + XnUInt32 nCount = 100; + + nRetVal = GetStreamNames(aStreamNames, &nCount); + XN_IS_STATUS_OK(nRetVal); + + for (XnUInt32 i = 0; i < nCount; ++i) + { + // find stream + XnDeviceStream* pStream = NULL; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + if (pStream->IsNewDataAvailable()) + { + *pbNewDataAvailable = TRUE; + *pnTimestamp = pStream->GetLastTimestamp(); + break; + } + } + } + else + { + // find stream + XnDeviceStream* pStream = NULL; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + if (pStream->IsNewDataAvailable()) + { + *pbNewDataAvailable = TRUE; + *pnTimestamp = pStream->GetLastTimestamp(); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read + nRetVal = pStream->Read(pStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pStreamData->bIsNew) + { + if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) == 0 || + strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) + { + // when primary stream is any, any stream read makes the device advance + m_nLastReadTimestamp = XN_MAX(pStreamData->nTimestamp, m_nLastReadTimestamp); + m_nLastReadFrameID = XN_MAX(pStreamData->nFrameID, m_nLastReadFrameID); + } + else if (strcmp(m_PrimaryStream.GetValue(), pStream->GetName()) == 0) + { + // this is the primary stream + m_nLastReadTimestamp = pStreamData->nTimestamp; + m_nLastReadFrameID = pStreamData->nFrameID; + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::ReadStream(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_WRITE) + { + return XN_STATUS_IO_DEVICE_WRONG_MODE; + } + + // take the stream to read + XnDeviceStream* pStream; + nRetVal = FindStream(pStreamOutput->StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + // make sure it is open + if (!pStream->IsNewDataAvailable() && !pStream->IsOpen()) + { + return XN_STATUS_STREAM_NOT_OPEN; + } + + // wait for it to advance + nRetVal = WaitForStream(m_hNewDataEvent, pStream); + XN_IS_STATUS_OK(nRetVal); + + // and read + nRetVal = ReadFromStreamImpl(pStream, pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::Read(XnStreamDataSet* pStreamOutputSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + + if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_WRITE) + { + return XN_STATUS_IO_DEVICE_WRONG_MODE; + } + + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_StreamsDataDump, "%llu,Read Called\n", nNow); + + // First thing to do is wait for primary stream to advance. We do this BEFORE checking streams + // because device streams might change during this wait. + nRetVal = WaitForPrimaryStream(m_hNewDataEvent, pStreamOutputSet); + XN_IS_STATUS_OK(nRetVal); + + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_StreamsDataDump, "%llu,Read Condition Met\n", nNow); + + // take the list of stream output objects + XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nOutputsCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + + nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, apStreamOutputs, &nOutputsCount); + XN_IS_STATUS_OK(nRetVal); + + // now read + for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) + { + // find its corresponding stream + XnDeviceStream* pStream; + nRetVal = FindStream(apStreamOutputs[nIndex]->StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReadFromStreamImpl(pStream, apStreamOutputs[nIndex]); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::WriteStream(XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamData); + + if (m_ReadWriteMode.GetValue() != XN_DEVICE_MODE_WRITE) + { + return XN_STATUS_IO_DEVICE_WRONG_MODE; + } + + // take the stream to write + XnDeviceStream* pStream; + nRetVal = FindStream(pStreamData->StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + // make sure it is open + if (!pStream->IsOpen()) + { + return XN_STATUS_STREAM_NOT_OPEN; + } + + // and write + nRetVal = pStream->Write(pStreamData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::Write(XnStreamDataSet* pStreamDataSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamDataSet); + + if (m_ReadWriteMode.GetValue() != XN_DEVICE_MODE_WRITE) + { + return XN_STATUS_IO_DEVICE_WRONG_MODE; + } + + // take the list of stream output objects + XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nOutputsCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + + nRetVal = XnStreamDataSetCopyToArray(pStreamDataSet, apStreamOutputs, &nOutputsCount); + XN_IS_STATUS_OK(nRetVal); + + // find the stream for each one + XnDeviceStream* apStreams[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + + for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) + { + // find its corresponding stream + nRetVal = FindStream(apStreamOutputs[nIndex]->StreamName, &apStreams[nIndex]); + XN_IS_STATUS_OK(nRetVal); + + // make sure it is open + if (!apStreams[nIndex]->IsOpen()) + { + return XN_STATUS_STREAM_NOT_OPEN; + } + } + + // go over them, and write into each one + for (XnUInt32 nIndex = 0; nIndex < nOutputsCount; ++nIndex) + { + nRetVal = apStreams[nIndex]->Write(apStreamOutputs[nIndex]); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::Tell(XnUInt64* pnTimestamp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OUTPUT_PTR(pnTimestamp); + + *pnTimestamp = m_nLastTimestamp; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::TellFrame(XnUInt32* pnFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OUTPUT_PTR(pnFrameID); + + *pnFrameID = m_nLastFrameID; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) +{ + XnStatus nRetVal = XN_STATUS_OK; + + *pbDoesExist = FALSE; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + if (nRetVal == XN_STATUS_DEVICE_MODULE_NOT_FOUND) + { + return XN_STATUS_OK; + } + else + { + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = pModule->DoesPropertyExist(PropertyName, pbDoesExist); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetPropertyType(PropertyName, pnType); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->SetProperty(PropertyName, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->SetProperty(PropertyName, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->SetProperty(PropertyName, csValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->SetProperty(PropertyName, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetProperty(PropertyName, pnValue); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetProperty(PropertyName, pdValue); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetProperty(PropertyName, csValue); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetProperty(PropertyName, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CreateStreamsFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // go through numbers until no stream is found + XnUInt32 nStreamIndex = 0; + XnChar csKeyName[XN_INI_MAX_LEN]; + + while (TRUE) + { + sprintf(csKeyName, "Stream%d_Type", nStreamIndex); + + XnChar csStreamType[XN_INI_MAX_LEN]; + XnChar csStreamName[XN_INI_MAX_LEN]; + + nRetVal = xnOSReadStringFromINI(csINIFilePath, csSectionName, csKeyName, csStreamType, XN_INI_MAX_LEN); + if (nRetVal != XN_STATUS_OK) // no more streams + { + break; + } + + // check if the stream has a name + sprintf(csKeyName, "Stream%d_Name", nStreamIndex); + nRetVal = xnOSReadStringFromINI(csINIFilePath, csSectionName, csKeyName, csStreamName, XN_INI_MAX_LEN); + if (nRetVal != XN_STATUS_OK) + { + // use its type as a name + strcpy(csStreamName, csStreamType); + } + + nRetVal = CreateStream(csStreamType, csStreamName); + XN_IS_STATUS_OK(nRetVal); + + nStreamIndex++; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = DeviceModule()->LoadConfigFromFile(csINIFilePath, csSectionName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::StartTransaction() +{ + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CommitTransaction() +{ + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::RollbackTransaction() +{ + return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; +} + +#define XN_CHECK_RC_ROLLBACK(rc) \ + if (rc != XN_STATUS_OK) \ + { \ + RollbackTransaction(); \ + return (rc); \ + } + +XnStatus XnDeviceBase::BatchConfig(const XnPropertySet* pChangeSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pChangeSet); + + // start a transaction + nRetVal = StartTransaction(); + XN_IS_STATUS_OK(nRetVal); + + for (XnPropertySetData::ConstIterator itModule = pChangeSet->pData->begin(); itModule != pChangeSet->pData->end(); ++itModule) + { + // find this module + XnDeviceModule* pModule = NULL; + nRetVal = FindModule(itModule.Key(), &pModule); + XN_CHECK_RC_ROLLBACK(nRetVal); + + nRetVal = pModule->BatchConfig(*itModule.Value()); + XN_CHECK_RC_ROLLBACK(nRetVal); + } + + nRetVal = CommitTransaction(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + + // clear the set + nRetVal = XnPropertySetClear(pSet); + XN_IS_STATUS_OK(nRetVal); + + if (strModule != NULL) + { + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->GetAllProperties(pSet); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // enumerate over modules + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + + if (bNoStreams && IsStream(pModuleHolder->GetModule())) + continue; + + nRetVal = pModuleHolder->GetModule()->GetAllProperties(pSet); + XN_IS_STATUS_OK(nRetVal); + } + } + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(Module, &pModule); + XN_IS_STATUS_OK(nRetVal); + + XnPropertyCallback* pRealCookie; + XN_VALIDATE_NEW(pRealCookie, XnPropertyCallback, GetDeviceHandle(), Module, PropertyName, Handler, pCookie); + + // register + nRetVal = pModule->RegisterForOnPropertyValueChanged(PropertyName, PropertyValueChangedCallback, pRealCookie, &pRealCookie->hCallback); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pRealCookie); + return (nRetVal); + } + + m_PropertyCallbacks.AddLast(pRealCookie); + + *phCallback = pRealCookie; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(Module); + XN_VALIDATE_INPUT_PTR(PropertyName); + XN_VALIDATE_INPUT_PTR(hCallback); + + XnPropertyCallback* pRealCookie = (XnPropertyCallback*)hCallback; + + XnDeviceModule* pModule; + nRetVal = FindModule(Module, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // first unregister it from property + nRetVal = pModule->UnregisterFromOnPropertyValueChanged(PropertyName, pRealCookie->hCallback); + XN_IS_STATUS_OK(nRetVal); + + XnValue val = pRealCookie; + XnList::Iterator it = m_PropertyCallbacks.Find(val); + if (it != m_PropertyCallbacks.end()) + { + m_PropertyCallbacks.Remove(it); + } + + // now free the memory + XN_DELETE(pRealCookie); + + return (XN_STATUS_OK); +} + +//--------------------------------------------------------------------------- +// Protected Helper Methods +//--------------------------------------------------------------------------- + +XnStatus XnDeviceBase::AddModule(XnDeviceModuleHolder* pModuleHolder) +{ + XnDeviceModule* pModule = pModuleHolder->GetModule(); + + // make sure module doesn't exist yet + XnStringsHash::Iterator it = m_Modules.end(); + if (XN_STATUS_OK == m_Modules.Find(pModule->GetName(), it)) + { + xnLogError(XN_MASK_DEVICE, "A module with the name %s already exists!", pModule->GetName()); + return XN_STATUS_ERROR; + } + + // add it to the list + XnStatus nRetVal = m_Modules.Set(pModule->GetName(), pModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::RemoveModule(const XnChar* ModuleName) +{ + // remove it + XnValue props; + XnStatus nRetVal = m_Modules.Remove(ModuleName, props); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::FindModule(const XnChar* ModuleName, XnDeviceModule** ppModule) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModuleHolder* pHolder; + nRetVal = FindModule(ModuleName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + *ppModule = pHolder->GetModule(); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::FindModule(const XnChar* ModuleName, XnDeviceModuleHolder** ppModuleHolder) +{ + XnStringsHash::Iterator it = m_Modules.end(); + XnStatus nRetVal = m_Modules.Find(ModuleName, it); + if (nRetVal == XN_STATUS_NO_MATCH) + { + return (XN_STATUS_DEVICE_MODULE_NOT_FOUND); + } + XN_IS_STATUS_OK(nRetVal); + + *ppModuleHolder = (XnDeviceModuleHolder*)it.Value(); + + return XN_STATUS_OK; +} + +XnBool XnDeviceBase::IsStream(XnDeviceModule* pModule) +{ + XnProperty* pProperty; + XnStatus nRetVal = pModule->GetProperty(XN_STREAM_PROPERTY_IS_STREAM, &pProperty); + if (nRetVal != XN_STATUS_OK) + return FALSE; + + if (pProperty->GetType() != XN_PROPERTY_TYPE_INTEGER) + return FALSE; + + XnIntProperty* pIntProperty = (XnIntProperty*)pProperty; + + XnUInt64 nValue; + nRetVal = pIntProperty->GetValue(&nValue); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_DDK, "Failed getting the value of the IsStream property: %s", xnGetStatusString(nRetVal)); + return FALSE; + } + + return (XnBool)nValue; +} + +XnStatus XnDeviceBase::FindStream(const XnChar* StreamName, XnDeviceStream** ppStream) +{ + // find the module + XnDeviceModuleHolder* pStreamHolder = NULL; + XnStatus nRetVal = FindStream(StreamName, &pStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + *ppStream = (XnDeviceStream*)pStreamHolder->GetModule(); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::FindStream(const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + // find the module + XnDeviceModuleHolder* pModuleHolder = NULL; + XnStatus nRetVal = FindModule(StreamName, &pModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + // check if this is a stream + if (!IsStream(pModuleHolder->GetModule())) + return XN_STATUS_MODULE_IS_NOT_STREAM; + + *ppStreamHolder = pModuleHolder; + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::AddSupportedStream(const XnChar* StreamType) +{ + // make sure stream doesn't exist yet + XnStringsHash::Iterator it = m_SupportedStreams.end(); + if (XN_STATUS_OK == m_SupportedStreams.Find(StreamType, it)) + { + xnLogError(XN_MASK_DEVICE, "A stream with the name %s already exists!", StreamType); + return XN_STATUS_STREAM_ALREADY_EXISTS; + } + + // add it to the list + XnStatus nRetVal = m_SupportedStreams.Set(StreamType, NULL); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetStreamRequiredDataSize(const XnChar* StreamName, XnUInt32* pnRequiredSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find stream + XnDeviceStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + *pnRequiredSize = pStream->GetRequiredDataSize(); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::CreateStreams(const XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnPropertySetData::ConstIterator it = pSet->pData->begin(); it != pSet->pData->end(); ++it) + { + // check if this module is a stream + XnActualPropertiesHash* pModule = it.Value(); + + XnActualPropertiesHash::ConstIterator itProp = pModule->end(); + if (XN_STATUS_OK == pModule->Find(XN_STREAM_PROPERTY_TYPE, itProp)) + { + // create a copy of the properties + XnActualPropertiesHash streamProps(it.Key()); + nRetVal = streamProps.CopyFrom(*pModule); + XN_IS_STATUS_OK(nRetVal); + + // remove the type property + nRetVal = streamProps.Remove(XN_STREAM_PROPERTY_TYPE); + XN_IS_STATUS_OK(nRetVal); + + // and create the stream + XnActualStringProperty* pActualProp = (XnActualStringProperty*)itProp.Value(); + nRetVal = CreateStreamImpl(pActualProp->GetValue(), it.Key(), &streamProps); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::ValidateOnlyModule(const XnPropertySet* pSet, const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnPropertySetData::ConstIterator it = pSet->pData->begin(); + if (it == pSet->pData->end()) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set did not contain any stream!"); + } + + if (strcmp(it.Key(), StreamName) != 0) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set module name does not match stream name!"); + } + + if (++it != pSet->pData->end()) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Property set contains more than one module!"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check for name + if (StreamName == NULL) + StreamName = StreamType; + + XnActualPropertiesHash* pInitialValuesHash = NULL; + + if (pInitialValues != NULL) + { + // validate property set + nRetVal = ValidateOnlyModule(pInitialValues, StreamName); + XN_IS_STATUS_OK(nRetVal); + + pInitialValuesHash = pInitialValues->pData->begin().Value(); + } + + nRetVal = CreateStreamImpl(StreamType, StreamName, pInitialValuesHash); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogInfo(XN_MASK_DDK, "Creating stream '%s' of type '%s'...", strName, strType); + + XnDeviceModule* pModule; + if (FindModule(strName, &pModule) == XN_STATUS_OK) + { + // already exists. check sharing mode (when shared, we allow "creating" the same stream) + if (GetSharingMode() != XN_DEVICE_SHARED || + !IsStream(pModule) || + strcmp(strType, ((XnDeviceStream*)pModule)->GetType()) != 0) + { + XN_LOG_WARNING_RETURN(XN_STATUS_STREAM_ALREADY_EXISTS, XN_MASK_DDK, "A stream with this name already exists!"); + } + + // OK, we'll allow this. Just set new configuration + if (pInitialSet != NULL) + { + nRetVal = pModule->BatchConfig(*pInitialSet); + XN_IS_STATUS_OK(nRetVal); + } + } + else + { + // create stream + XnDeviceModuleHolder* pNewStreamHolder = NULL; + + nRetVal = CreateStreamModule(strType, strName, &pNewStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + XnDeviceStream* pNewStream = (XnDeviceStream*)(pNewStreamHolder->GetModule()); + if (pNewStream == NULL) + { + DestroyStreamModule(pNewStreamHolder); + XN_LOG_ERROR_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Internal Error: Invalid new stream!"); + } + + // initialize the stream + xnLogVerbose(XN_MASK_DDK, "Initializing stream '%s'...", strName); + + nRetVal = pNewStreamHolder->Init(pInitialSet); + if (nRetVal != XN_STATUS_OK) + { + DestroyStreamModule(pNewStreamHolder); + return (nRetVal); + } + + // set it's mirror value (if not requested otherwise) + XnBool bSetMirror = TRUE; + + if (pInitialSet != NULL) + { + XnActualPropertiesHash::ConstIterator it = pInitialSet->end(); + if (XN_STATUS_OK == pInitialSet->Find(XN_MODULE_PROPERTY_MIRROR, it)) + { + bSetMirror = FALSE; + } + } + + if (bSetMirror) + { + nRetVal = pNewStream->SetMirror((XnBool)m_DeviceMirror.GetValue()); + if (nRetVal != XN_STATUS_OK) + { + DestroyStreamModule(pNewStreamHolder); + return (nRetVal); + } + } + + // add it to the list of existing modules + nRetVal = AddModule(pNewStreamHolder); + if (nRetVal != XN_STATUS_OK) + { + DestroyStreamModule(pNewStreamHolder); + return (nRetVal); + } + + xnLogInfo(XN_MASK_DDK, "Stream '%s' was initialized.", strName); + + nRetVal = StreamAdded(pNewStream); + XN_IS_STATUS_OK(nRetVal); + + xnLogInfo(XN_MASK_DDK, "'%s' stream was created.", strName); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::StreamAdded(XnDeviceStream* pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // register to the NewData event + if (m_ReadWriteMode.GetValue() == XN_DEVICE_MODE_READ) + { + pStream->SetNewDataCallback(NewStreamDataCallback, this); + } + + // raise the change event + m_OnStreamsChangeEvent.Raise(GetDeviceHandle(), pStream->GetName(), XN_DEVICE_STREAM_ADDED); + + return (XN_STATUS_OK); +} + +void XnDeviceBase::FreeModuleRegisteredProperties(const XnChar* strModule) +{ + // free memory of registered properties to this stream + XnList::Iterator it = m_PropertyCallbacks.begin(); + while (it != m_PropertyCallbacks.end()) + { + XnList::Iterator cur = it; + it++; + + XnPropertyCallback* pRealCallback = (XnPropertyCallback*)*cur; + if (strcmp(pRealCallback->strModule, strModule) == 0) + { + m_PropertyCallbacks.Remove(cur); + XN_DELETE(pRealCallback); + } + } +} + +XnStatus XnDeviceBase::DestroyStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogInfo(XN_MASK_DDK, "Destroying stream '%s'...", StreamName); + + // keep the stream name (we now delete the module, so the name will be lost) + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + strncpy(strStreamName, StreamName, XN_DEVICE_MAX_STRING_LENGTH); + + // Find the stream + XnDeviceModuleHolder* pStreamHolder; + nRetVal = FindStream(strStreamName, &pStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + // remove it from map + nRetVal = RemoveModule(strStreamName); + XN_IS_STATUS_OK(nRetVal); + + // and free it's memory + DestroyStreamModule(pStreamHolder); + + // free memory of registered properties to this stream + FreeModuleRegisteredProperties(StreamName); + + // raise event + m_OnStreamsChangeEvent.Raise(GetDeviceHandle(), strStreamName, XN_DEVICE_STREAM_DELETED); + + xnLogVerbose(XN_MASK_DDK, "'%s' stream destroyed.", strStreamName); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolder** apModules, XnUInt32* pnCount) +{ + XnUInt32 nCount = 0; + + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + apModules[nCount] = (XnDeviceModuleHolder*)it.Value(); + nCount++; + } + + *pnCount = nCount; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolderList& list) +{ + XnStatus nRetVal = XN_STATUS_OK; + + list.Clear(); + + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + list.AddLast((XnDeviceModuleHolder*)it.Value()); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::GetStreamsList(XnDeviceModuleHolderList& list) +{ + XnStatus nRetVal = XN_STATUS_OK; + + list.Clear(); + + for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it) + { + XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value(); + if (IsStream(pModuleHolder->GetModule())) + { + list.AddLast(pModuleHolder); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::RaiseNewStreamDataEvent(const XnChar* StreamName) +{ + m_OnNewStreamDataEvent.Raise(GetDeviceHandle(), StreamName); + + return XN_STATUS_OK; +} + +void XnDeviceBase::OnNewStreamData(XnDeviceStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID) +{ + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_StreamsDataDump, "%llu,%s,%llu,%u\n", nNow, pStream->GetName(), nTimestamp, nFrameID); + + if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) == 0 || + strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) + { + // any stream makes us advance + m_nLastTimestamp = XN_MAX(m_nLastTimestamp, nTimestamp); + m_nLastFrameID = XN_MAX(m_nLastFrameID, nFrameID); + } + else if (strcmp(m_PrimaryStream.GetValue(), pStream->GetName()) == 0) // this stream is the primary + { + m_nLastTimestamp = nTimestamp; + m_nLastFrameID = nFrameID; + } + + XnStatus nRetVal = xnOSSetEvent(m_hNewDataEvent); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_DDK, "Failed setting the new data event: %s", xnGetStatusString(nRetVal)); + } + + RaiseNewStreamDataEvent(pStream->GetName()); +} + +void XnDeviceBase::ResetLastTimestampAndFrame() +{ + m_nLastFrameID = 0; + m_nLastTimestamp = 0; + m_nLastReadFrameID = 0; + m_nLastReadTimestamp = 0; +} + +void XnDeviceBase::NewStreamDataCallback(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie) +{ + XnDeviceBase* pThis = (XnDeviceBase*)pCookie; + pThis->OnNewStreamData(pSender, nTimestamp, nFrameID); +} + +XnBool XnDeviceBase::HasPrimaryStreamAdvanced(XnStreamDataSet* pOutputSet) +{ + if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_NONE) == 0) + { + // special case of None: condition is always true + return TRUE; + } + + const XnChar* astrNames[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nArraySize = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + + // take a list of streams to check for new data + if (strcmp(m_PrimaryStream.GetValue(), XN_PRIMARY_STREAM_ANY) != 0) + { + // we have a specific stream. Add it to the list + astrNames[0] = m_PrimaryStream.GetValue(); + nArraySize = 1; + } + else + { + // special case of ANY. we need to check every one of requested streams + XnStreamData* apStreamOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + if (XN_STATUS_OK != XnStreamDataSetCopyToArray(pOutputSet, apStreamOutputs, &nArraySize)) + { + return FALSE; + } + + for (XnUInt32 i = 0; i < nArraySize; ++i) + { + astrNames[i] = apStreamOutputs[i]->StreamName; + } + } + + // now check if we have new data + for (XnUInt32 i = 0; i < nArraySize; ++i) + { + XnDeviceStream* pStream = NULL; + if (XN_STATUS_OK == FindStream(astrNames[i], &pStream)) + { + if (pStream->IsNewDataAvailable()) + return TRUE; + } + } + + return FALSE; +} + +XnBool XnDeviceBase::HasStreamAdvanced(XnDeviceStream* pStream) +{ + return pStream->IsNewDataAvailable(); +} + +XnBool XnDeviceBase::HasPrimaryStreamAdvancedCallback(void* pCookie) +{ + XnWaitForPrimaryData* pWaitData = (XnWaitForPrimaryData*)pCookie; + return pWaitData->pThis->HasPrimaryStreamAdvanced(pWaitData->pSet); +} + +XnBool XnDeviceBase::HasStreamAdvancedCallback(void* pCookie) +{ + XnWaitForStreamData* pWaitData = (XnWaitForStreamData*)pCookie; + return pWaitData->pThis->HasStreamAdvanced(pWaitData->pStream); +} + +XnStatus XnDeviceBase::WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnWaitForStreamData WaitData; + WaitData.pThis = this; + WaitData.pStream = pStream; + nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnDeviceBase::HasStreamAdvancedCallback, &WaitData); + if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) + { + xnLogError(XN_MASK_DDK, "Not responding - stream did not advance!"); + return (XN_STATUS_IO_DEVICE_NOT_RESPONDING); + } + else + { + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceBase::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnWaitForPrimaryData WaitData; + WaitData.pThis = this; + WaitData.pSet = pSet; + nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnDeviceBase::HasPrimaryStreamAdvancedCallback, &WaitData); + if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) + { + xnLogError(XN_MASK_DDK, "Not responding - primary stream did not advance!"); + return (XN_STATUS_IO_DEVICE_NOT_RESPONDING); + } + else + { + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceBase::PropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnPropertyCallback* pUserCallback = (XnPropertyCallback*)pCookie; + + // TODO: consider catching exceptions (if user does some stupid things) + pUserCallback->pHandler(pUserCallback->DeviceHandle, pUserCallback->strModule, pUserCallback->strProp, pUserCallback->pCookie); + + return XN_STATUS_OK; +} + +XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetPrimaryStreamCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie) +{ + XnDeviceBase* pThis = (XnDeviceBase*)pCookie; + return pThis->SetPrimaryStream(strValue); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceBase* pThis = (XnDeviceBase*)pCookie; + return pThis->SetMirror((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceBase::SetHighresTimestampsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceBase* pThis = (XnDeviceBase*)pCookie; + return pThis->SetHighresTimestamps((XnBool)nValue); +} + diff --git a/Source/XnDDK/XnDeviceBase.h b/Source/XnDDK/XnDeviceBase.h index 50e1ab4..81b9bd5 100644 --- a/Source/XnDDK/XnDeviceBase.h +++ b/Source/XnDDK/XnDeviceBase.h @@ -1,313 +1,313 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_BASE_H__ -#define __XN_DEVICE_BASE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include "XnDeviceModuleHolder.h" -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_MASK_DEVICE "Device" -#define XN_DEVICE_BASE_MAX_STREAMS_COUNT 100 - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -class XN_DDK_CPP_API XnDeviceBase : public IXnDevice -{ -public: - XnDeviceBase(const XnChar* csName, XnBool bStrictProperties); - ~XnDeviceBase(); - - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& ReadWriteModeProperty() { return m_ReadWriteMode; } - inline XnActualStringProperty& PrimaryStreamProperty() { return m_PrimaryStream; } - inline XnActualIntProperty& DeviceMirrorProperty() { return m_DeviceMirror; } - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnDeviceMode GetReadWriteMode() const { return (XnDeviceMode)m_ReadWriteMode.GetValue(); } - inline const XnChar* GetPrimaryStream() const { return m_PrimaryStream.GetValue(); } - inline XnBool GetDeviceMirror() const { return (XnBool)m_DeviceMirror.GetValue(); } - inline XnBool IsHighResTimestamps() const { return (XnBool)m_HighResTimestamps.GetValue(); } - - inline XnDeviceModule* DeviceModule() { return m_pDevicePropertiesHolder->GetModule(); } - inline XnDeviceModuleHolder* DeviceModuleHolder() { return m_pDevicePropertiesHolder; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetPrimaryStream(const XnChar* strPrimaryStream); - virtual XnStatus SetMirror(XnBool bMirror); - virtual XnStatus SetHighresTimestamps(XnBool bHighRes); - - //--------------------------------------------------------------------------- - // Helpers - //--------------------------------------------------------------------------- - static inline XnDeviceBase* GetFromDeviceHandle(XnDeviceHandle DeviceHandle) { return (XnDeviceBase*)DeviceHandle; } - - //--------------------------------------------------------------------------- - // IXnDevice Methods - //--------------------------------------------------------------------------- - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus Destroy(); - virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount); - virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); - virtual XnStatus DestroyStream(const XnChar* StreamName); - virtual XnStatus OpenStream(const XnChar* StreamName); - virtual XnStatus CloseStream(const XnChar* StreamName); - virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount); - virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist); - virtual XnStatus OpenAllStreams(); - virtual XnStatus CloseAllStreams(); - virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); - virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback); - virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData); - static XnStatus DestroyStreamData(XnStreamData** ppStreamData); - virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); - virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback); - virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp); - virtual XnStatus ReadStream(XnStreamData* pStreamOutput); - virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet); - virtual XnStatus WriteStream(XnStreamData* pStreamOutput); - virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet); - virtual XnStatus Tell(XnUInt64* pnTimestamp); - virtual XnStatus TellFrame(XnUInt32* pnFrameID); - virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist); - virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType); - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue); - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue); - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue); - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue); - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& pValue); - virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); - virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet); - virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL); - virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); - virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback); - - XN_DECLARE_EVENT_3ARG(StreamCollectionChangedEvent, StreamCollectionChangedEventInterface, XnDeviceHandle, DeviceHandle, const XnChar*, StreamName, XnStreamsChangeEventType, EventType); - StreamCollectionChangedEventInterface& OnStreamCollectionChangedEvent() { return m_OnStreamsChangeEvent; } - - XN_DECLARE_EVENT_2ARG(NewStreamDataEvent, NewStreamDataEventInterface, XnDeviceHandle, DeviceHandle, const XnChar*, StreamName); - NewStreamDataEventInterface& OnNewStreamDataEvent() { return m_OnNewStreamDataEvent; } - -protected: - virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet); - - virtual XnStatus CreateModule(const XnChar* strName, XnDeviceModuleHolder** ppModuleHolder); - virtual XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); - virtual void DestroyModule(XnDeviceModuleHolder* pModuleHolder); - - XnStatus CreateStreams(const XnPropertySet* pSet); - - /** - * Adds a module to the device modules. - */ - XnStatus AddModule(XnDeviceModuleHolder* pModuleHolder); - - /** - * Removes a module from the device modules. - */ - XnStatus RemoveModule(const XnChar* ModuleName); - - /** - * Finds a module. - */ - XnStatus FindModule(const XnChar* ModuleName, XnDeviceModule** ppModule); - - /** - * Finds a module. - */ - XnStatus FindModule(const XnChar* ModuleName, XnDeviceModuleHolder** ppModuleHolder); - - /** - * Checks if a module is a stream. - */ - static XnBool IsStream(XnDeviceModule* pModule); - - /** - * Finds a stream (a module which has the IS_STREAM property set to TRUE). - */ - XnStatus FindStream(const XnChar* StreamName, XnDeviceStream** ppStream); - - /** - * Finds a stream holder (a module which has the IS_STREAM property set to TRUE). - */ - XnStatus FindStream(const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); - - /** - * Adds a stream to the list of supported streams. - */ - XnStatus AddSupportedStream(const XnChar* StreamType); - - /** - * Creates a stream. - * - * @param StreamType [in] Type of the stream to create. - * @param StreamName [in] The name of the new stream. - */ - virtual XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) = 0; - - virtual void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) = 0; - - /** - * Starts a transaction. - */ - virtual XnStatus StartTransaction(); - - /** - * Commits a transaction. - */ - virtual XnStatus CommitTransaction(); - - /** - * Rollbacks a transaction. - */ - virtual XnStatus RollbackTransaction(); - - /** - * Gets the required output size of a stream. - */ - XnStatus GetStreamRequiredDataSize(const XnChar* StreamName, XnUInt32* pnRequiredSize); - - /** - * Gets the list of modules the device supports. - * - * @param aModules [out] an array of modules. - * @param pnModules [out] The number of modules. - */ - XnStatus GetModulesList(XnDeviceModuleHolder** apModules, XnUInt32* pnCount); - XnStatus GetModulesList(XnDeviceModuleHolderList& list); - - XnStatus GetStreamsList(XnDeviceModuleHolderList& list); - - /** - * Raises the NewStreamData event. - * - * @param StreamName [in] The name of the stream with new data. - */ - XnStatus RaiseNewStreamDataEvent(const XnChar* StreamName); - - /** Gets called when a stream has new data. */ - virtual void OnNewStreamData(XnDeviceStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID); - - virtual XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); - virtual XnStatus WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream); - - XnBool HasPrimaryStreamAdvanced(XnStreamDataSet* pSet); - XnBool HasStreamAdvanced(XnDeviceStream* pStream); - - inline XnUInt64 GetLastReadTimestamp() const { return m_nLastReadTimestamp; } - inline XnUInt32 GetLastReadFrameID() const { return m_nLastReadFrameID; } - - inline XnUInt64 GetLastTimestamp() const { return m_nLastTimestamp; } - inline XnUInt32 GetLastFrameID() const { return m_nLastFrameID; } - - void ResetLastTimestampAndFrame(); - XnStatus ValidateOnlyModule(const XnPropertySet* pSet, const XnChar* StreamName); - XnStatus CreateStreamsFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); - - XnStatus StreamAdded(XnDeviceStream* pStream); - - inline XnDeviceSharingMode GetSharingMode() const { return (XnDeviceSharingMode)m_SharingMode.GetValue(); } - - -private: - typedef XnBool (XnDeviceBase::*ConditionFuncPtr)(void*); - - static XnBool XN_CALLBACK_TYPE HasPrimaryStreamAdvancedCallback(void* pSet); - static XnBool XN_CALLBACK_TYPE HasStreamAdvancedCallback(void* pStream); - - XnStatus ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamData); - void FreeModuleRegisteredProperties(const XnChar* strModule); - - static XnStatus XN_CALLBACK_TYPE PropertyValueChangedCallback(const XnProperty* pSender, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetPrimaryStreamCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetHighresTimestampsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - static void NewStreamDataCallback(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie); - - XnBool m_bStrictProperties; - - XnDeviceModuleHolder* m_pDevicePropertiesHolder; - XnActualIntProperty m_ReadWriteMode; - XnActualIntProperty m_SharingMode; - XnActualStringProperty m_PrimaryStream; - XnActualIntProperty m_DeviceMirror; - XnActualGeneralProperty m_SDKVersionProp; - XnActualIntProperty m_HighResTimestamps; - XnActualStringProperty m_DeviceName; - - /** Used to tell the read thread new data is available. */ - XN_EVENT_HANDLE m_hNewDataEvent; - - /** Keeps the last read timestamp and frame id. */ - XnUInt64 m_nLastReadTimestamp; - XnUInt32 m_nLastReadFrameID; - - /** Keeps the latest available timestamp and frame id. */ - XnUInt64 m_nLastTimestamp; - XnUInt32 m_nLastFrameID; - - static XnStatus XN_CALLBACK_TYPE StreamNewDataCallback(XnDeviceStream* pStream, void* pCookie); - - XnStringsHash m_Modules; - XnStringsHash m_SupportedStreams; - - XnList m_PropertyCallbacks; - - StreamCollectionChangedEvent m_OnStreamsChangeEvent; - NewStreamDataEvent m_OnNewStreamDataEvent; - - XnSDKVersion m_SDKVersion; - XnDump m_StreamsDataDump; -}; - -#endif //__XN_DEVICE_BASE_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_BASE_H__ +#define __XN_DEVICE_BASE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include "XnDeviceModuleHolder.h" +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MASK_DEVICE "Device" +#define XN_DEVICE_BASE_MAX_STREAMS_COUNT 100 + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +class XN_DDK_CPP_API XnDeviceBase : public IXnDevice +{ +public: + XnDeviceBase(const XnChar* csName, XnBool bStrictProperties); + ~XnDeviceBase(); + + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& ReadWriteModeProperty() { return m_ReadWriteMode; } + inline XnActualStringProperty& PrimaryStreamProperty() { return m_PrimaryStream; } + inline XnActualIntProperty& DeviceMirrorProperty() { return m_DeviceMirror; } + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnDeviceMode GetReadWriteMode() const { return (XnDeviceMode)m_ReadWriteMode.GetValue(); } + inline const XnChar* GetPrimaryStream() const { return m_PrimaryStream.GetValue(); } + inline XnBool GetDeviceMirror() const { return (XnBool)m_DeviceMirror.GetValue(); } + inline XnBool IsHighResTimestamps() const { return (XnBool)m_HighResTimestamps.GetValue(); } + + inline XnDeviceModule* DeviceModule() { return m_pDevicePropertiesHolder->GetModule(); } + inline XnDeviceModuleHolder* DeviceModuleHolder() { return m_pDevicePropertiesHolder; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetPrimaryStream(const XnChar* strPrimaryStream); + virtual XnStatus SetMirror(XnBool bMirror); + virtual XnStatus SetHighresTimestamps(XnBool bHighRes); + + //--------------------------------------------------------------------------- + // Helpers + //--------------------------------------------------------------------------- + static inline XnDeviceBase* GetFromDeviceHandle(XnDeviceHandle DeviceHandle) { return (XnDeviceBase*)DeviceHandle; } + + //--------------------------------------------------------------------------- + // IXnDevice Methods + //--------------------------------------------------------------------------- + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus Destroy(); + virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount); + virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); + virtual XnStatus DestroyStream(const XnChar* StreamName); + virtual XnStatus OpenStream(const XnChar* StreamName); + virtual XnStatus CloseStream(const XnChar* StreamName); + virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount); + virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist); + virtual XnStatus OpenAllStreams(); + virtual XnStatus CloseAllStreams(); + virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); + virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback); + virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData); + static XnStatus DestroyStreamData(XnStreamData** ppStreamData); + virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); + virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback); + virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp); + virtual XnStatus ReadStream(XnStreamData* pStreamOutput); + virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet); + virtual XnStatus WriteStream(XnStreamData* pStreamOutput); + virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet); + virtual XnStatus Tell(XnUInt64* pnTimestamp); + virtual XnStatus TellFrame(XnUInt32* pnFrameID); + virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist); + virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType); + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue); + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue); + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue); + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue); + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& pValue); + virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); + virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet); + virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL); + virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback); + virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback); + + XN_DECLARE_EVENT_3ARG(StreamCollectionChangedEvent, StreamCollectionChangedEventInterface, XnDeviceHandle, DeviceHandle, const XnChar*, StreamName, XnStreamsChangeEventType, EventType); + StreamCollectionChangedEventInterface& OnStreamCollectionChangedEvent() { return m_OnStreamsChangeEvent; } + + XN_DECLARE_EVENT_2ARG(NewStreamDataEvent, NewStreamDataEventInterface, XnDeviceHandle, DeviceHandle, const XnChar*, StreamName); + NewStreamDataEventInterface& OnNewStreamDataEvent() { return m_OnNewStreamDataEvent; } + +protected: + virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet); + + virtual XnStatus CreateModule(const XnChar* strName, XnDeviceModuleHolder** ppModuleHolder); + virtual XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); + virtual void DestroyModule(XnDeviceModuleHolder* pModuleHolder); + + XnStatus CreateStreams(const XnPropertySet* pSet); + + /** + * Adds a module to the device modules. + */ + XnStatus AddModule(XnDeviceModuleHolder* pModuleHolder); + + /** + * Removes a module from the device modules. + */ + XnStatus RemoveModule(const XnChar* ModuleName); + + /** + * Finds a module. + */ + XnStatus FindModule(const XnChar* ModuleName, XnDeviceModule** ppModule); + + /** + * Finds a module. + */ + XnStatus FindModule(const XnChar* ModuleName, XnDeviceModuleHolder** ppModuleHolder); + + /** + * Checks if a module is a stream. + */ + static XnBool IsStream(XnDeviceModule* pModule); + + /** + * Finds a stream (a module which has the IS_STREAM property set to TRUE). + */ + XnStatus FindStream(const XnChar* StreamName, XnDeviceStream** ppStream); + + /** + * Finds a stream holder (a module which has the IS_STREAM property set to TRUE). + */ + XnStatus FindStream(const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); + + /** + * Adds a stream to the list of supported streams. + */ + XnStatus AddSupportedStream(const XnChar* StreamType); + + /** + * Creates a stream. + * + * @param StreamType [in] Type of the stream to create. + * @param StreamName [in] The name of the new stream. + */ + virtual XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) = 0; + + virtual void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) = 0; + + /** + * Starts a transaction. + */ + virtual XnStatus StartTransaction(); + + /** + * Commits a transaction. + */ + virtual XnStatus CommitTransaction(); + + /** + * Rollbacks a transaction. + */ + virtual XnStatus RollbackTransaction(); + + /** + * Gets the required output size of a stream. + */ + XnStatus GetStreamRequiredDataSize(const XnChar* StreamName, XnUInt32* pnRequiredSize); + + /** + * Gets the list of modules the device supports. + * + * @param aModules [out] an array of modules. + * @param pnModules [out] The number of modules. + */ + XnStatus GetModulesList(XnDeviceModuleHolder** apModules, XnUInt32* pnCount); + XnStatus GetModulesList(XnDeviceModuleHolderList& list); + + XnStatus GetStreamsList(XnDeviceModuleHolderList& list); + + /** + * Raises the NewStreamData event. + * + * @param StreamName [in] The name of the stream with new data. + */ + XnStatus RaiseNewStreamDataEvent(const XnChar* StreamName); + + /** Gets called when a stream has new data. */ + virtual void OnNewStreamData(XnDeviceStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID); + + virtual XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); + virtual XnStatus WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream); + + XnBool HasPrimaryStreamAdvanced(XnStreamDataSet* pSet); + XnBool HasStreamAdvanced(XnDeviceStream* pStream); + + inline XnUInt64 GetLastReadTimestamp() const { return m_nLastReadTimestamp; } + inline XnUInt32 GetLastReadFrameID() const { return m_nLastReadFrameID; } + + inline XnUInt64 GetLastTimestamp() const { return m_nLastTimestamp; } + inline XnUInt32 GetLastFrameID() const { return m_nLastFrameID; } + + void ResetLastTimestampAndFrame(); + XnStatus ValidateOnlyModule(const XnPropertySet* pSet, const XnChar* StreamName); + XnStatus CreateStreamsFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); + + XnStatus StreamAdded(XnDeviceStream* pStream); + + inline XnDeviceSharingMode GetSharingMode() const { return (XnDeviceSharingMode)m_SharingMode.GetValue(); } + + +private: + typedef XnBool (XnDeviceBase::*ConditionFuncPtr)(void*); + + static XnBool XN_CALLBACK_TYPE HasPrimaryStreamAdvancedCallback(void* pSet); + static XnBool XN_CALLBACK_TYPE HasStreamAdvancedCallback(void* pStream); + + XnStatus ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamData); + void FreeModuleRegisteredProperties(const XnChar* strModule); + + static XnStatus XN_CALLBACK_TYPE PropertyValueChangedCallback(const XnProperty* pSender, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetPrimaryStreamCallback(XnActualStringProperty* pSender, const XnChar* strValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetHighresTimestampsCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + static void NewStreamDataCallback(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie); + + XnBool m_bStrictProperties; + + XnDeviceModuleHolder* m_pDevicePropertiesHolder; + XnActualIntProperty m_ReadWriteMode; + XnActualIntProperty m_SharingMode; + XnActualStringProperty m_PrimaryStream; + XnActualIntProperty m_DeviceMirror; + XnActualGeneralProperty m_SDKVersionProp; + XnActualIntProperty m_HighResTimestamps; + XnActualStringProperty m_DeviceName; + + /** Used to tell the read thread new data is available. */ + XN_EVENT_HANDLE m_hNewDataEvent; + + /** Keeps the last read timestamp and frame id. */ + XnUInt64 m_nLastReadTimestamp; + XnUInt32 m_nLastReadFrameID; + + /** Keeps the latest available timestamp and frame id. */ + XnUInt64 m_nLastTimestamp; + XnUInt32 m_nLastFrameID; + + static XnStatus XN_CALLBACK_TYPE StreamNewDataCallback(XnDeviceStream* pStream, void* pCookie); + + XnStringsHash m_Modules; + XnStringsHash m_SupportedStreams; + + XnList m_PropertyCallbacks; + + StreamCollectionChangedEvent m_OnStreamsChangeEvent; + NewStreamDataEvent m_OnNewStreamDataEvent; + + XnSDKVersion m_SDKVersion; + XnDump m_StreamsDataDump; +}; + +#endif //__XN_DEVICE_BASE_H__ diff --git a/Source/XnDDK/XnDeviceBaseProxy.cpp b/Source/XnDDK/XnDeviceBaseProxy.cpp index 828efd5..ecae583 100644 --- a/Source/XnDDK/XnDeviceBaseProxy.cpp +++ b/Source/XnDDK/XnDeviceBaseProxy.cpp @@ -1,31 +1,31 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- #include "XnDeviceBaseProxy.h" \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceBaseProxy.h b/Source/XnDDK/XnDeviceBaseProxy.h index 6424fee..94afffc 100644 --- a/Source/XnDDK/XnDeviceBaseProxy.h +++ b/Source/XnDDK/XnDeviceBaseProxy.h @@ -1,309 +1,309 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_BASE_PROXY_H__ -#define __XN_DEVICE_BASE_PROXY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "IXnDevice.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_VALIDATE_ACTUAL_DEVICE \ - if (m_pActual == NULL) return XN_STATUS_ERROR; - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* A base class for all proxies. By default, every call gets transfered to the actual device. -* Deriving classes may add additional behavior. -*/ -class XN_DDK_CPP_API XnDeviceBaseProxy : public IXnDevice -{ -public: - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Init(pDeviceConfig); - } - - virtual XnStatus Destroy() - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Destroy(); - } - - virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetSupportedStreams(aStreamNames, pnStreamNamesCount); - } - - virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->CreateStream(StreamType, StreamName, pInitialValues); - } - - virtual XnStatus DestroyStream(const XnChar* StreamName) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->DestroyStream(StreamName); - } - - virtual XnStatus OpenStream(const XnChar* StreamName) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->OpenStream(StreamName); - } - - virtual XnStatus CloseStream(const XnChar* StreamName) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->CloseStream(StreamName); - } - - virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetStreamNames(pstrNames, pnNamesCount); - } - - virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->DoesModuleExist(ModuleName, pbDoesExist); - } - - virtual XnStatus OpenAllStreams() - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->OpenAllStreams(); - } - - virtual XnStatus CloseAllStreams() - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->CloseAllStreams(); - } - - virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->RegisterToStreamsChange(Handler, pCookie, phCallback); - } - - virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->UnregisterFromStreamsChange(hCallback); - } - - virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->CreateStreamData(StreamName, ppStreamData); - } - - virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->RegisterToNewStreamData(Handler, pCookie, phCallback); - } - - virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->UnregisterFromNewStreamData(hCallback); - } - - virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->IsNewDataAvailable(StreamName, pbNewDataAvailable, pnTimestamp); - } - - virtual XnStatus ReadStream(XnStreamData* pStreamOutput) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->ReadStream(pStreamOutput); - } - - virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Read(pStreamOutputSet); - } - - virtual XnStatus WriteStream(XnStreamData* pStreamOutput) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->WriteStream(pStreamOutput); - } - - virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Write(pStreamOutputSet); - } - - virtual XnStatus Tell(XnUInt64* pnTimestamp) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Tell(pnTimestamp); - } - - virtual XnStatus Seek(XnUInt64 nTimestamp) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->Seek(nTimestamp); - } - - virtual XnStatus TellFrame(XnUInt32* pnFrameID) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->TellFrame(pnFrameID); - } - - virtual XnStatus SeekFrame(XnUInt32 nFrameID) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->SeekFrame(nFrameID); - } - - virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->DoesPropertyExist(ModuleName, PropertyName, pbDoesExist); - } - - virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetPropertyType(ModuleName, PropertyName, pnType); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->SetProperty(ModuleName, PropertyName, nValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->SetProperty(ModuleName, PropertyName, dValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->SetProperty(ModuleName, PropertyName, csValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->SetProperty(ModuleName, PropertyName, Value); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetProperty(ModuleName, PropertyName, pnValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetProperty(ModuleName, PropertyName, pdValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetProperty(ModuleName, PropertyName, csValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetProperty(ModuleName, PropertyName, gbValue); - } - - virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->LoadConfigFromFile(csINIFilePath, csSectionName); - } - - virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->BatchConfig(pChangeSet); - } - - virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->GetAllProperties(pSet, bNoStreams, strModule); - } - - virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->RegisterToPropertyChange(Module, PropertyName, Handler, pCookie, phCallback); - } - - virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) - { - XN_VALIDATE_ACTUAL_DEVICE; - return m_pActual->UnregisterFromPropertyChange(Module, PropertyName, hCallback); - } - -protected: - XnDeviceBaseProxy(IXnDevice* pActual) - { - ReplaceActualDevice(pActual); - } - - IXnDevice* GetActual() { return m_pActual; } - - void ReplaceActualDevice(IXnDevice* pActual) - { - m_pActual = pActual; - } - -private: - IXnDevice* m_pActual; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_BASE_PROXY_H__ +#define __XN_DEVICE_BASE_PROXY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "IXnDevice.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_VALIDATE_ACTUAL_DEVICE \ + if (m_pActual == NULL) return XN_STATUS_ERROR; + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* A base class for all proxies. By default, every call gets transfered to the actual device. +* Deriving classes may add additional behavior. +*/ +class XN_DDK_CPP_API XnDeviceBaseProxy : public IXnDevice +{ +public: + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Init(pDeviceConfig); + } + + virtual XnStatus Destroy() + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Destroy(); + } + + virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetSupportedStreams(aStreamNames, pnStreamNamesCount); + } + + virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->CreateStream(StreamType, StreamName, pInitialValues); + } + + virtual XnStatus DestroyStream(const XnChar* StreamName) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->DestroyStream(StreamName); + } + + virtual XnStatus OpenStream(const XnChar* StreamName) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->OpenStream(StreamName); + } + + virtual XnStatus CloseStream(const XnChar* StreamName) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->CloseStream(StreamName); + } + + virtual XnStatus GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetStreamNames(pstrNames, pnNamesCount); + } + + virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->DoesModuleExist(ModuleName, pbDoesExist); + } + + virtual XnStatus OpenAllStreams() + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->OpenAllStreams(); + } + + virtual XnStatus CloseAllStreams() + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->CloseAllStreams(); + } + + virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->RegisterToStreamsChange(Handler, pCookie, phCallback); + } + + virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->UnregisterFromStreamsChange(hCallback); + } + + virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->CreateStreamData(StreamName, ppStreamData); + } + + virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->RegisterToNewStreamData(Handler, pCookie, phCallback); + } + + virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->UnregisterFromNewStreamData(hCallback); + } + + virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->IsNewDataAvailable(StreamName, pbNewDataAvailable, pnTimestamp); + } + + virtual XnStatus ReadStream(XnStreamData* pStreamOutput) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->ReadStream(pStreamOutput); + } + + virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Read(pStreamOutputSet); + } + + virtual XnStatus WriteStream(XnStreamData* pStreamOutput) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->WriteStream(pStreamOutput); + } + + virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Write(pStreamOutputSet); + } + + virtual XnStatus Tell(XnUInt64* pnTimestamp) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Tell(pnTimestamp); + } + + virtual XnStatus Seek(XnUInt64 nTimestamp) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->Seek(nTimestamp); + } + + virtual XnStatus TellFrame(XnUInt32* pnFrameID) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->TellFrame(pnFrameID); + } + + virtual XnStatus SeekFrame(XnUInt32 nFrameID) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->SeekFrame(nFrameID); + } + + virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->DoesPropertyExist(ModuleName, PropertyName, pbDoesExist); + } + + virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetPropertyType(ModuleName, PropertyName, pnType); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->SetProperty(ModuleName, PropertyName, nValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->SetProperty(ModuleName, PropertyName, dValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->SetProperty(ModuleName, PropertyName, csValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->SetProperty(ModuleName, PropertyName, Value); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetProperty(ModuleName, PropertyName, pnValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetProperty(ModuleName, PropertyName, pdValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetProperty(ModuleName, PropertyName, csValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetProperty(ModuleName, PropertyName, gbValue); + } + + virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->LoadConfigFromFile(csINIFilePath, csSectionName); + } + + virtual XnStatus BatchConfig(const XnPropertySet* pChangeSet) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->BatchConfig(pChangeSet); + } + + virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->GetAllProperties(pSet, bNoStreams, strModule); + } + + virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->RegisterToPropertyChange(Module, PropertyName, Handler, pCookie, phCallback); + } + + virtual XnStatus UnregisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) + { + XN_VALIDATE_ACTUAL_DEVICE; + return m_pActual->UnregisterFromPropertyChange(Module, PropertyName, hCallback); + } + +protected: + XnDeviceBaseProxy(IXnDevice* pActual) + { + ReplaceActualDevice(pActual); + } + + IXnDevice* GetActual() { return m_pActual; } + + void ReplaceActualDevice(IXnDevice* pActual) + { + m_pActual = pActual; + } + +private: + IXnDevice* m_pActual; +}; + #endif //__XN_DEVICE_BASE_PROXY_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceFunctionsTypedefs.h b/Source/XnDDK/XnDeviceFunctionsTypedefs.h index b864975..bdbe420 100644 --- a/Source/XnDDK/XnDeviceFunctionsTypedefs.h +++ b/Source/XnDDK/XnDeviceFunctionsTypedefs.h @@ -1,36 +1,36 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_DEVICE_FUNCTIONS_TYPEDEFS_H__ -#define __XN_DEVICE_FUNCTIONS_TYPEDEFS_H__ - -// create a list of typedefs - -#define XN_DEVICE_TYPEDEF_NAME(name) XnDevice##name##FuncPtr -#define XN_DEVICE_INTERFACE_FUNCTION(name, sig) typedef XnStatus (*XN_DEVICE_TYPEDEF_NAME(name))sig; -#include -#undef XN_DEVICE_INTERFACE_FUNCTION - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_DEVICE_FUNCTIONS_TYPEDEFS_H__ +#define __XN_DEVICE_FUNCTIONS_TYPEDEFS_H__ + +// create a list of typedefs + +#define XN_DEVICE_TYPEDEF_NAME(name) XnDevice##name##FuncPtr +#define XN_DEVICE_INTERFACE_FUNCTION(name, sig) typedef XnStatus (*XN_DEVICE_TYPEDEF_NAME(name))sig; +#include +#undef XN_DEVICE_INTERFACE_FUNCTION + #endif //__XN_DEVICE_FUNCTIONS_TYPEDEFS_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceInterfaceAdapter.h b/Source/XnDDK/XnDeviceInterfaceAdapter.h index 2fae8f0..2e3b166 100644 --- a/Source/XnDDK/XnDeviceInterfaceAdapter.h +++ b/Source/XnDDK/XnDeviceInterfaceAdapter.h @@ -1,236 +1,236 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_INTERFACE_ADAPTER_H__ -#define __XN_DEVICE_INTERFACE_ADAPTER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "IXnDevice.h" -#include "XnDeviceManager.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnDeviceInterfaceAdapter : public IXnDevice -{ -public: - XnDeviceInterfaceAdapter(XnDeviceInterfaceFunctions* pFuncs) : - m_pFuncs(pFuncs) - {} - - ~XnDeviceInterfaceAdapter() - { - Destroy(); - } - - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) - { - return m_pFuncs->Create(&m_Handle, pDeviceConfig); - } - - virtual XnStatus Destroy() - { - return m_pFuncs->Destroy(&m_Handle); - } - - virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) - { - return m_pFuncs->GetSupportedStreams(m_Handle, aStreamNames, pnStreamNamesCount); - } - - virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) - { - return m_pFuncs->CreateStream(m_Handle, StreamType, StreamName, pInitialValues); - } - - virtual XnStatus DestroyStream(const XnChar* StreamName) - { - return m_pFuncs->DestroyStream(m_Handle, StreamName); - } - - virtual XnStatus OpenStream(const XnChar* StreamName) - { - return m_pFuncs->OpenStream(m_Handle, StreamName); - } - - virtual XnStatus CloseStream(const XnChar* StreamName) - { - return m_pFuncs->CloseStream(m_Handle, StreamName); - } - - virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) - { - return m_pFuncs->DoesModuleExist(m_Handle, ModuleName, pbDoesExist); - } - - virtual XnStatus OpenAllStreams() - { - return m_pFuncs->OpenAllStreams(m_Handle); - } - - virtual XnStatus CloseAllStreams() - { - return m_pFuncs->CloseAllStreams(m_Handle); - } - - virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - return m_pFuncs->RegisterToStreamsChange(m_Handle, Handler, pCookie, phCallback); - } - - virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) - { - return m_pFuncs->UnregisterFromStreamsChange(m_Handle, hCallback); - } - - virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) - { - return m_pFuncs->CreateStreamData(m_Handle, StreamName, ppStreamData); - } - - virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - return m_pFuncs->RegisterToNewStreamData(m_Handle, Handler, pCookie, phCallback); - } - - virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) - { - return m_pFuncs->UnregisterFromNewStreamData(m_Handle, hCallback); - } - - virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) - { - return m_pFuncs->IsNewDataAvailable(m_Handle, StreamName, pbNewDataAvailable, pnTimestamp); - } - - virtual XnStatus ReadStream(XnStreamData* pStreamOutput) - { - return m_pFuncs->ReadStream(m_Handle, pStreamOutput); - } - - virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) - { - return m_pFuncs->Read(m_Handle, pStreamOutputSet); - } - - virtual XnStatus WriteStream(XnStreamData* pStreamOutput) - { - return m_pFuncs->WriteStream(m_Handle, pStreamOutput); - } - - virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) - { - return m_pFuncs->Write(m_Handle, pStreamOutputSet); - } - - virtual XnStatus Tell(XnUInt64* pnTimestamp) - { - return m_pFuncs->Tell(m_Handle, pnTimestamp); - } - - virtual XnStatus Seek(XnUInt64 nTimestamp) - { - return m_pFuncs->Seek(m_Handle, nTimestamp); - } - - virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) - { - return m_pFuncs->DoesPropertyExist(m_Handle, ModuleName, PropertyName, pbDoesExist); - } - - virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) - { - return m_pFuncs->GetPropertyType(m_Handle, ModuleName, PropertyName, pnType); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) - { - return m_pFuncs->SetIntProperty(m_Handle, ModuleName, PropertyName, nValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) - { - return m_pFuncs->SetRealProperty(m_Handle, ModuleName, PropertyName, dValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) - { - return m_pFuncs->SetStringProperty(m_Handle, ModuleName, PropertyName, csValue); - } - - virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) - { - return m_pFuncs->SetGeneralProperty(m_Handle, ModuleName, PropertyName, Value); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) - { - return m_pFuncs->GetIntProperty(m_Handle, ModuleName, PropertyName, pnValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) - { - return m_pFuncs->GetRealProperty(m_Handle, ModuleName, PropertyName, pdValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) - { - return m_pFuncs->GetStringProperty(m_Handle, ModuleName, PropertyName, csValue); - } - - virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer* pValue) - { - return m_pFuncs->GetGeneralProperty(m_Handle, ModuleName, PropertyName, pValue); - } - - virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) - { - return m_pFuncs->LoadConfigFromFile(m_Handle, csINIFilePath, csSectionName); - } - - virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) - { - return m_pFuncs->GetAllProperties(m_Handle, pSet, bNoStreams, strModule); - } - - virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) - { - return m_pFuncs->RegisterToPropertyChange(m_Handle, Module, PropertyName, Handler, pCookie, phCallback); - } - - virtual XnStatus UnRegisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) - { - return m_pFuncs->UnregisterFromPropertyChange(m_Handle, Module, PropertyName, hCallback); - } - -private: - XnDeviceInterfaceFunctions* m_pFuncs; - XnDeviceHandle m_Handle; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_INTERFACE_ADAPTER_H__ +#define __XN_DEVICE_INTERFACE_ADAPTER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "IXnDevice.h" +#include "XnDeviceManager.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnDeviceInterfaceAdapter : public IXnDevice +{ +public: + XnDeviceInterfaceAdapter(XnDeviceInterfaceFunctions* pFuncs) : + m_pFuncs(pFuncs) + {} + + ~XnDeviceInterfaceAdapter() + { + Destroy(); + } + + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig) + { + return m_pFuncs->Create(&m_Handle, pDeviceConfig); + } + + virtual XnStatus Destroy() + { + return m_pFuncs->Destroy(&m_Handle); + } + + virtual XnStatus GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount) + { + return m_pFuncs->GetSupportedStreams(m_Handle, aStreamNames, pnStreamNamesCount); + } + + virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL) + { + return m_pFuncs->CreateStream(m_Handle, StreamType, StreamName, pInitialValues); + } + + virtual XnStatus DestroyStream(const XnChar* StreamName) + { + return m_pFuncs->DestroyStream(m_Handle, StreamName); + } + + virtual XnStatus OpenStream(const XnChar* StreamName) + { + return m_pFuncs->OpenStream(m_Handle, StreamName); + } + + virtual XnStatus CloseStream(const XnChar* StreamName) + { + return m_pFuncs->CloseStream(m_Handle, StreamName); + } + + virtual XnStatus DoesModuleExist(const XnChar* ModuleName, XnBool* pbDoesExist) + { + return m_pFuncs->DoesModuleExist(m_Handle, ModuleName, pbDoesExist); + } + + virtual XnStatus OpenAllStreams() + { + return m_pFuncs->OpenAllStreams(m_Handle); + } + + virtual XnStatus CloseAllStreams() + { + return m_pFuncs->CloseAllStreams(m_Handle); + } + + virtual XnStatus RegisterToStreamsChange(XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + return m_pFuncs->RegisterToStreamsChange(m_Handle, Handler, pCookie, phCallback); + } + + virtual XnStatus UnregisterFromStreamsChange(XnCallbackHandle hCallback) + { + return m_pFuncs->UnregisterFromStreamsChange(m_Handle, hCallback); + } + + virtual XnStatus CreateStreamData(const XnChar* StreamName, XnStreamData** ppStreamData) + { + return m_pFuncs->CreateStreamData(m_Handle, StreamName, ppStreamData); + } + + virtual XnStatus RegisterToNewStreamData(XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + return m_pFuncs->RegisterToNewStreamData(m_Handle, Handler, pCookie, phCallback); + } + + virtual XnStatus UnregisterFromNewStreamData(XnCallbackHandle hCallback) + { + return m_pFuncs->UnregisterFromNewStreamData(m_Handle, hCallback); + } + + virtual XnStatus IsNewDataAvailable(const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) + { + return m_pFuncs->IsNewDataAvailable(m_Handle, StreamName, pbNewDataAvailable, pnTimestamp); + } + + virtual XnStatus ReadStream(XnStreamData* pStreamOutput) + { + return m_pFuncs->ReadStream(m_Handle, pStreamOutput); + } + + virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet) + { + return m_pFuncs->Read(m_Handle, pStreamOutputSet); + } + + virtual XnStatus WriteStream(XnStreamData* pStreamOutput) + { + return m_pFuncs->WriteStream(m_Handle, pStreamOutput); + } + + virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet) + { + return m_pFuncs->Write(m_Handle, pStreamOutputSet); + } + + virtual XnStatus Tell(XnUInt64* pnTimestamp) + { + return m_pFuncs->Tell(m_Handle, pnTimestamp); + } + + virtual XnStatus Seek(XnUInt64 nTimestamp) + { + return m_pFuncs->Seek(m_Handle, nTimestamp); + } + + virtual XnStatus DoesPropertyExist(const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) + { + return m_pFuncs->DoesPropertyExist(m_Handle, ModuleName, PropertyName, pbDoesExist); + } + + virtual XnStatus GetPropertyType(const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) + { + return m_pFuncs->GetPropertyType(m_Handle, ModuleName, PropertyName, pnType); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) + { + return m_pFuncs->SetIntProperty(m_Handle, ModuleName, PropertyName, nValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) + { + return m_pFuncs->SetRealProperty(m_Handle, ModuleName, PropertyName, dValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) + { + return m_pFuncs->SetStringProperty(m_Handle, ModuleName, PropertyName, csValue); + } + + virtual XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) + { + return m_pFuncs->SetGeneralProperty(m_Handle, ModuleName, PropertyName, Value); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) + { + return m_pFuncs->GetIntProperty(m_Handle, ModuleName, PropertyName, pnValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) + { + return m_pFuncs->GetRealProperty(m_Handle, ModuleName, PropertyName, pdValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) + { + return m_pFuncs->GetStringProperty(m_Handle, ModuleName, PropertyName, csValue); + } + + virtual XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer* pValue) + { + return m_pFuncs->GetGeneralProperty(m_Handle, ModuleName, PropertyName, pValue); + } + + virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) + { + return m_pFuncs->LoadConfigFromFile(m_Handle, csINIFilePath, csSectionName); + } + + virtual XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL) + { + return m_pFuncs->GetAllProperties(m_Handle, pSet, bNoStreams, strModule); + } + + virtual XnStatus RegisterToPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) + { + return m_pFuncs->RegisterToPropertyChange(m_Handle, Module, PropertyName, Handler, pCookie, phCallback); + } + + virtual XnStatus UnRegisterFromPropertyChange(const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) + { + return m_pFuncs->UnregisterFromPropertyChange(m_Handle, Module, PropertyName, hCallback); + } + +private: + XnDeviceInterfaceFunctions* m_pFuncs; + XnDeviceHandle m_Handle; +}; + #endif //__XN_DEVICE_INTERFACE_ADAPTER_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceInterfaceImpl.h b/Source/XnDDK/XnDeviceInterfaceImpl.h index b725f7d..b73676a 100644 --- a/Source/XnDDK/XnDeviceInterfaceImpl.h +++ b/Source/XnDDK/XnDeviceInterfaceImpl.h @@ -1,313 +1,313 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -/** -* This file is intended to allow any IXnDevice derivative to export its interface for -* a "C" environment. -* To use, one must first define the following: -* XN_DEVICE_BASE_DERIVATIVE - the name of the class inheriting from IXnDevice. -* XN_DEVICE_BASE_DERIVATIVE_PREFIX (optional) - a prefix for function names. -*/ - -#ifndef XN_DEVICE_BASE_DERIVATIVE -#error "To use this file, XN_DEVICE_BASE_DERIVATIVE must be defined as the class inheriting from IXnDevice" -#endif - -#include -#include - -// use default prefix, if one is not provided -#ifndef XN_DEVICE_BASE_DERIVATIVE_PREFIX -#define XN_DEVICE_BASE_DERIVATIVE_PREFIX XN_DEVICE_EXPORT_PREFIX -#endif - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetDefinition)(XnDeviceDefinition* pDeviceDefinition) -{ - return XN_DEVICE_BASE_DERIVATIVE::GetDefinition(pDeviceDefinition); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Enumerate)(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - return XN_DEVICE_BASE_DERIVATIVE::Enumerate(aConnectionStrings, pnCount); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Create)(XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) -{ - IXnDevice* pDevice = XN_NEW(XN_DEVICE_BASE_DERIVATIVE); - XnStatus nRetVal = pDevice->Init(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - *pDeviceHandle = pDevice->GetDeviceHandle(); - - return XN_STATUS_OK; -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Destroy)(XnDeviceHandle* pDeviceHandle) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(*pDeviceHandle); - XnStatus nRetVal = pDevice->Destroy(); - XN_IS_STATUS_OK(nRetVal); - - XN_DELETE(pDevice); - *pDeviceHandle = NULL; - - return XN_STATUS_OK; -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetSupportedStreams)(const XnDeviceHandle DeviceHandle, const XnChar** aStreamName, XnUInt32* pnStreamNamesCount) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetSupportedStreams(aStreamName, pnStreamNamesCount); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CreateStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamType, const XnChar* StreamName, const XnPropertySet* pInitialValues) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->CreateStream(StreamType, StreamName, pInitialValues); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DestroyStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->DestroyStream(StreamName); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(OpenStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->OpenStream(StreamName); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CloseStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->CloseStream(StreamName); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(OpenAllStreams)(const XnDeviceHandle DeviceHandle) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->OpenAllStreams(); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CloseAllStreams)(const XnDeviceHandle DeviceHandle) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->CloseAllStreams(); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetStreamNames)(const XnDeviceHandle DeviceHandle, const XnChar** pstrNames, XnUInt32* pnNamesCount) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetStreamNames(pstrNames, pnNamesCount); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DoesModuleExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, XnBool* pbDoesExist) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->DoesModuleExist(ModuleName, pbDoesExist); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToStreamsChange)(const XnDeviceHandle DeviceHandle, XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->RegisterToStreamsChange(Handler, pCookie, phCallback); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromStreamsChange)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->UnregisterFromStreamsChange(hCallback); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CreateStreamData)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamData** ppStreamData) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->CreateStreamData(StreamName, ppStreamData); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DestroyStreamData)(XnStreamData** ppStreamData) -{ - return XN_DEVICE_BASE_DERIVATIVE::DestroyStreamData(ppStreamData); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToNewStreamData)(const XnDeviceHandle DeviceHandle, XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->RegisterToNewStreamData(Handler, pCookie, phCallback); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromNewStreamData)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->UnregisterFromNewStreamData(hCallback); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(IsNewDataAvailable)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->IsNewDataAvailable(StreamName, pbNewDataAvailable, pnTimestamp); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(ReadStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->ReadStream(pStreamOutput); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Read)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->Read(pStreamOutputSet); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(WriteStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->WriteStream(pStreamOutput); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Write)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->Write(pStreamOutputSet); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Tell)(const XnDeviceHandle DeviceHandle, XnUInt64* pnTimestamp) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->Tell(pnTimestamp); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Seek)(const XnDeviceHandle DeviceHandle, XnUInt64 nTimestamp) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->Seek(nTimestamp); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(TellFrame)(const XnDeviceHandle DeviceHandle, XnUInt32* pnFrameID) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->TellFrame(pnFrameID); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SeekFrame)(const XnDeviceHandle DeviceHandle, XnUInt32 nFrameID) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->SeekFrame(nFrameID); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DoesPropertyExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->DoesPropertyExist(ModuleName, PropertyName, pbDoesExist); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetPropertyType)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetPropertyType(ModuleName, PropertyName, pnType); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->SetProperty(ModuleName, PropertyName, nValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->SetProperty(ModuleName, PropertyName, dValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->SetProperty(ModuleName, PropertyName, csValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->SetProperty(ModuleName, PropertyName, Value); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetProperty(ModuleName, PropertyName, pnValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetProperty(ModuleName, PropertyName, pdValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetProperty(ModuleName, PropertyName, csValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer* pValue) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetProperty(ModuleName, PropertyName, *pValue); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(LoadConfigFromFile)(const XnDeviceHandle DeviceHandle, const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->LoadConfigFromFile(csINIFilePath, csSectionName); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(BatchConfig)(const XnDeviceHandle DeviceHandle, const XnPropertySet* pChangeSet) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->BatchConfig(pChangeSet); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetAllProperties)(const XnDeviceHandle DeviceHandle, XnPropertySet* pPropertySet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->GetAllProperties(pPropertySet, bNoStreams, strModule); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->RegisterToPropertyChange(Module, PropertyName, Handler, pCookie, phCallback); -} - -XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) -{ - IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); - return pDevice->UnregisterFromPropertyChange(Module, PropertyName, hCallback); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +/** +* This file is intended to allow any IXnDevice derivative to export its interface for +* a "C" environment. +* To use, one must first define the following: +* XN_DEVICE_BASE_DERIVATIVE - the name of the class inheriting from IXnDevice. +* XN_DEVICE_BASE_DERIVATIVE_PREFIX (optional) - a prefix for function names. +*/ + +#ifndef XN_DEVICE_BASE_DERIVATIVE +#error "To use this file, XN_DEVICE_BASE_DERIVATIVE must be defined as the class inheriting from IXnDevice" +#endif + +#include +#include + +// use default prefix, if one is not provided +#ifndef XN_DEVICE_BASE_DERIVATIVE_PREFIX +#define XN_DEVICE_BASE_DERIVATIVE_PREFIX XN_DEVICE_EXPORT_PREFIX +#endif + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetDefinition)(XnDeviceDefinition* pDeviceDefinition) +{ + return XN_DEVICE_BASE_DERIVATIVE::GetDefinition(pDeviceDefinition); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Enumerate)(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + return XN_DEVICE_BASE_DERIVATIVE::Enumerate(aConnectionStrings, pnCount); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Create)(XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) +{ + IXnDevice* pDevice = XN_NEW(XN_DEVICE_BASE_DERIVATIVE); + XnStatus nRetVal = pDevice->Init(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + *pDeviceHandle = pDevice->GetDeviceHandle(); + + return XN_STATUS_OK; +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Destroy)(XnDeviceHandle* pDeviceHandle) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(*pDeviceHandle); + XnStatus nRetVal = pDevice->Destroy(); + XN_IS_STATUS_OK(nRetVal); + + XN_DELETE(pDevice); + *pDeviceHandle = NULL; + + return XN_STATUS_OK; +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetSupportedStreams)(const XnDeviceHandle DeviceHandle, const XnChar** aStreamName, XnUInt32* pnStreamNamesCount) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetSupportedStreams(aStreamName, pnStreamNamesCount); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CreateStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamType, const XnChar* StreamName, const XnPropertySet* pInitialValues) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->CreateStream(StreamType, StreamName, pInitialValues); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DestroyStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->DestroyStream(StreamName); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(OpenStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->OpenStream(StreamName); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CloseStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->CloseStream(StreamName); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(OpenAllStreams)(const XnDeviceHandle DeviceHandle) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->OpenAllStreams(); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CloseAllStreams)(const XnDeviceHandle DeviceHandle) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->CloseAllStreams(); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetStreamNames)(const XnDeviceHandle DeviceHandle, const XnChar** pstrNames, XnUInt32* pnNamesCount) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetStreamNames(pstrNames, pnNamesCount); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DoesModuleExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, XnBool* pbDoesExist) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->DoesModuleExist(ModuleName, pbDoesExist); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToStreamsChange)(const XnDeviceHandle DeviceHandle, XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->RegisterToStreamsChange(Handler, pCookie, phCallback); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromStreamsChange)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->UnregisterFromStreamsChange(hCallback); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(CreateStreamData)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamData** ppStreamData) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->CreateStreamData(StreamName, ppStreamData); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DestroyStreamData)(XnStreamData** ppStreamData) +{ + return XN_DEVICE_BASE_DERIVATIVE::DestroyStreamData(ppStreamData); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToNewStreamData)(const XnDeviceHandle DeviceHandle, XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->RegisterToNewStreamData(Handler, pCookie, phCallback); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromNewStreamData)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->UnregisterFromNewStreamData(hCallback); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(IsNewDataAvailable)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->IsNewDataAvailable(StreamName, pbNewDataAvailable, pnTimestamp); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(ReadStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->ReadStream(pStreamOutput); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Read)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->Read(pStreamOutputSet); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(WriteStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->WriteStream(pStreamOutput); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Write)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->Write(pStreamOutputSet); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Tell)(const XnDeviceHandle DeviceHandle, XnUInt64* pnTimestamp) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->Tell(pnTimestamp); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(Seek)(const XnDeviceHandle DeviceHandle, XnUInt64 nTimestamp) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->Seek(nTimestamp); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(TellFrame)(const XnDeviceHandle DeviceHandle, XnUInt32* pnFrameID) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->TellFrame(pnFrameID); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SeekFrame)(const XnDeviceHandle DeviceHandle, XnUInt32 nFrameID) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->SeekFrame(nFrameID); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(DoesPropertyExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->DoesPropertyExist(ModuleName, PropertyName, pbDoesExist); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetPropertyType)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetPropertyType(ModuleName, PropertyName, pnType); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->SetProperty(ModuleName, PropertyName, nValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->SetProperty(ModuleName, PropertyName, dValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->SetProperty(ModuleName, PropertyName, csValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(SetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->SetProperty(ModuleName, PropertyName, Value); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetProperty(ModuleName, PropertyName, pnValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetProperty(ModuleName, PropertyName, pdValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetProperty(ModuleName, PropertyName, csValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer* pValue) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetProperty(ModuleName, PropertyName, *pValue); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(LoadConfigFromFile)(const XnDeviceHandle DeviceHandle, const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->LoadConfigFromFile(csINIFilePath, csSectionName); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(BatchConfig)(const XnDeviceHandle DeviceHandle, const XnPropertySet* pChangeSet) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->BatchConfig(pChangeSet); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(GetAllProperties)(const XnDeviceHandle DeviceHandle, XnPropertySet* pPropertySet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->GetAllProperties(pPropertySet, bNoStreams, strModule); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(RegisterToPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->RegisterToPropertyChange(Module, PropertyName, Handler, pCookie, phCallback); +} + +XN_DEVICE_API XnStatus XN_DEVICE_PROTO_NAME(UnregisterFromPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) +{ + IXnDevice* pDevice = IXnDevice::GetFromDeviceHandle(DeviceHandle); + return pDevice->UnregisterFromPropertyChange(Module, PropertyName, hCallback); +} + diff --git a/Source/XnDDK/XnDeviceManager.cpp b/Source/XnDDK/XnDeviceManager.cpp index 188e77c..22bc5fa 100644 --- a/Source/XnDDK/XnDeviceManager.cpp +++ b/Source/XnDDK/XnDeviceManager.cpp @@ -1,308 +1,308 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceManager.h" -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_MASK_DEVICE_MANAGER "DeviceManager" - -/** The shared library file name prefix for Xiron I/O device files. */ -#define XN_DEVICE_FILE_PREFIX "XnDevice" - -#define XN_DEVICE_MANAGER_FIND_FUNC_IN_LIB(lib, name, descriptor, rc) \ - rc = xnOSGetProcAddress(lib, XN_STRINGIFY(XN_DEVICE_PROTO_NAME(name)), (XnFarProc*)&descriptor->Interface.name); \ - if (rc != XN_STATUS_OK) \ - { \ - xnOSFreeLibrary(lib); \ - xnLogError(XN_MASK_DEVICE_MANAGER, "Failed to find function %s!", XN_STRINGIFY(XN_DEVICE_PROTO_NAME(name))); \ - return (rc); \ - } - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnDeviceManagerData -{ - XnDeviceDescriptor aDevices[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES]; - XnUInt32 nDevicesCount; -} XnDeviceManagerData; - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -XnDeviceManagerData* g_pDeviceManager = NULL; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnDeviceManagerUpdateDefinition(XnDeviceDescriptor* pDescriptor) -{ - return pDescriptor->Interface.GetDefinition(&pDescriptor->Definition); -} - -#ifdef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS - -XnStatus XnDeviceManagerLoadDevice(const XnChar* csFileName, XnDeviceDescriptor* pDescriptor) -{ - // first load library - XnStatus nRetVal = xnOSLoadLibrary(csFileName, &pDescriptor->hLib); - XN_IS_STATUS_OK(nRetVal); - - // now search for all functions in device interface - - // NOTE: the following lines will cause each function to be found and stored in the descriptor - #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) XN_DEVICE_MANAGER_FIND_FUNC_IN_LIB(pDescriptor->hLib, name, pDescriptor, nRetVal) - #include - #undef XN_DEVICE_INTERFACE_FUNCTION - - return XnDeviceManagerUpdateDefinition(pDescriptor); -} - -XnStatus XnDeviceManagerLoadAllDevices(const XnChar* strDir) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar cpSearchString[XN_FILE_MAX_PATH] = ""; - - if (strDir == NULL) - { - strDir = XN_FILE_LOCAL_DIR; - } - - // Build the search pattern string - XN_VALIDATE_STR_APPEND(cpSearchString, strDir, XN_FILE_MAX_PATH, nRetVal); - XN_VALIDATE_STR_APPEND(cpSearchString, XN_FILE_DIR_SEP, XN_FILE_MAX_PATH, nRetVal); - XN_VALIDATE_STR_APPEND(cpSearchString, XN_SHARED_LIBRARY_PREFIX, XN_FILE_MAX_PATH, nRetVal); - XN_VALIDATE_STR_APPEND(cpSearchString, XN_DEVICE_FILE_PREFIX, XN_FILE_MAX_PATH, nRetVal); - XN_VALIDATE_STR_APPEND(cpSearchString, XN_FILE_ALL_WILDCARD, XN_FILE_MAX_PATH, nRetVal); - XN_VALIDATE_STR_APPEND(cpSearchString, XN_SHARED_LIBRARY_POSTFIX, XN_FILE_MAX_PATH, nRetVal); - - // Get a file list of Xiron devices - XnChar acsFileList[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES][XN_FILE_MAX_PATH]; - XnUInt32 nFileCount = 0; - - xnLogVerbose(XN_MASK_DEVICE_MANAGER, "Searching for %s...", cpSearchString); - nRetVal = xnOSGetFileList(cpSearchString, NULL, acsFileList, XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES, &nFileCount); - if ((nRetVal != XN_STATUS_OS_FILE_NOT_FOUND) && (nRetVal != XN_STATUS_OK)) - { - return (nRetVal); - } - - // now try to load each file - for (XnUInt32 nIndex = 0; nIndex < nFileCount; ++nIndex) - { - xnLogVerbose(XN_MASK_DEVICE_MANAGER, "Trying to load a device '%s'...", acsFileList[nIndex]); - nRetVal = XnDeviceManagerLoadDevice(acsFileList[nIndex], &g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_DEVICE_MANAGER, "'%s' is not a valid device: %s", acsFileList[nIndex], xnGetStatusString(nRetVal)); - } - else - { - xnLogInfo(XN_MASK_DEVICE_MANAGER, "device '%s' loaded.", acsFileList[nIndex]); - g_pDeviceManager->nDevicesCount++; - } - } - - return (XN_STATUS_OK); -} - -#else // no dynamic libs - -XnStatus XnDeviceManagerLoadAllDevices() -{ - XnStatus nRetVal = XN_STATUS_OK; - - #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) pDescriptor->Interface.name = XN_DEVICE_PROTO_NAME(name); - - XnDeviceDescriptor* pDescriptor = g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]; - - #define XN_DEVICE_EXPORT_PREFIX SensorV2_ - #include - #undef XN_DEVICE_EXPORT_PREFIX - - nRetVal = XnDeviceManagerUpdateDefinition(pDescriptor); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_DEVICE_MANAGER, "'SensorV2' is not a valid device: %s", xnGetStatusString(nRetVal)); - } - else - { - g_pDeviceManager->nDevicesCount++; - } - - XnDeviceDescriptor* pDescriptor = g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]; - - #define XN_DEVICE_EXPORT_PREFIX File_ - #include - #undef XN_DEVICE_EXPORT_PREFIX - - nRetVal = XnDeviceManagerUpdateDefinition(pDescriptor); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_DEVICE_MANAGER, "'SensorV2' is not a valid device: %s", xnGetStatusString(nRetVal)); - } - else - { - g_pDeviceManager->nDevicesCount++; - } - - #undef XN_DEVICE_INTERFACE_FUNCTION - - return (XN_STATUS_OK) -} - -#endif - -XnStatus XnDeviceManagerInit(const XnChar* strDevicesDir) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if device manager is already initialized - if (g_pDeviceManager != NULL) - { - return XN_STATUS_ALREADY_INIT; - } - - // allocate data - XN_VALIDATE_ALLOC(g_pDeviceManager, XnDeviceManagerData); - g_pDeviceManager->nDevicesCount = 0; - - // load devices - nRetVal = XnDeviceManagerLoadAllDevices(strDevicesDir); - XN_IS_STATUS_OK(nRetVal); - - // make sure we found at least one device - if (g_pDeviceManager->nDevicesCount == 0) - { - return (XN_STATUS_IO_NO_DEVICES); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceManagerShutdown() -{ -#ifdef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS - // unload all libraries - for (XnUInt32 i = 0; i < g_pDeviceManager->nDevicesCount; ++i) - { - xnOSFreeLibrary(g_pDeviceManager->aDevices[i].hLib); - } -#endif - - // check if device manager is initialized - if (g_pDeviceManager == NULL) - { - return XN_STATUS_NOT_INIT; - } - - // free data - XN_FREE_AND_NULL(g_pDeviceManager); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceManagerGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if device manager is initialized - if (g_pDeviceManager == NULL) - { - return XN_STATUS_NOT_INIT; - } - - // check count - XnUInt32 nArraySize = *pnCount; - - *pnCount = g_pDeviceManager->nDevicesCount; - - if (nArraySize < g_pDeviceManager->nDevicesCount) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - // copy definitions - for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) - { - aDeviceDefinitions[nIndex] = g_pDeviceManager->aDevices[nIndex].Definition; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceManagerGetDeviceByName(const XnChar* csName, XnDeviceDescriptor** ppDeviceDescriptor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if device manager is initialized - if (g_pDeviceManager == NULL) - { - return XN_STATUS_NOT_INIT; - } - - // special case: AUTO - if (strncmp(csName, XN_DEVICE_MANAGER_AUTO_NAME, strlen(XN_DEVICE_MANAGER_AUTO_NAME)) == 0) - { - for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) - { - // Get a pointer to the current device descriptor - XnDeviceDescriptor* pDescriptor = &g_pDeviceManager->aDevices[nIndex]; - - XnUInt32 nCount = 0; - nRetVal = pDescriptor->Interface.Enumerate(NULL, &nCount); - if (nCount > 0) - { - *ppDeviceDescriptor = pDescriptor; - return (XN_STATUS_OK); - } - } - } - else - { - // search by name - for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) - { - if (strcmp(g_pDeviceManager->aDevices[nIndex].Definition.cpName, csName) == 0) - { - *ppDeviceDescriptor = &g_pDeviceManager->aDevices[nIndex]; - return (XN_STATUS_OK); - } - } - } - - return (XN_STATUS_IO_DEVICE_NOT_FOUND); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceManager.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MASK_DEVICE_MANAGER "DeviceManager" + +/** The shared library file name prefix for Xiron I/O device files. */ +#define XN_DEVICE_FILE_PREFIX "XnDevice" + +#define XN_DEVICE_MANAGER_FIND_FUNC_IN_LIB(lib, name, descriptor, rc) \ + rc = xnOSGetProcAddress(lib, XN_STRINGIFY(XN_DEVICE_PROTO_NAME(name)), (XnFarProc*)&descriptor->Interface.name); \ + if (rc != XN_STATUS_OK) \ + { \ + xnOSFreeLibrary(lib); \ + xnLogError(XN_MASK_DEVICE_MANAGER, "Failed to find function %s!", XN_STRINGIFY(XN_DEVICE_PROTO_NAME(name))); \ + return (rc); \ + } + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnDeviceManagerData +{ + XnDeviceDescriptor aDevices[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES]; + XnUInt32 nDevicesCount; +} XnDeviceManagerData; + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +XnDeviceManagerData* g_pDeviceManager = NULL; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnDeviceManagerUpdateDefinition(XnDeviceDescriptor* pDescriptor) +{ + return pDescriptor->Interface.GetDefinition(&pDescriptor->Definition); +} + +#ifdef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS + +XnStatus XnDeviceManagerLoadDevice(const XnChar* csFileName, XnDeviceDescriptor* pDescriptor) +{ + // first load library + XnStatus nRetVal = xnOSLoadLibrary(csFileName, &pDescriptor->hLib); + XN_IS_STATUS_OK(nRetVal); + + // now search for all functions in device interface + + // NOTE: the following lines will cause each function to be found and stored in the descriptor + #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) XN_DEVICE_MANAGER_FIND_FUNC_IN_LIB(pDescriptor->hLib, name, pDescriptor, nRetVal) + #include + #undef XN_DEVICE_INTERFACE_FUNCTION + + return XnDeviceManagerUpdateDefinition(pDescriptor); +} + +XnStatus XnDeviceManagerLoadAllDevices(const XnChar* strDir) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar cpSearchString[XN_FILE_MAX_PATH] = ""; + + if (strDir == NULL) + { + strDir = XN_FILE_LOCAL_DIR; + } + + // Build the search pattern string + XN_VALIDATE_STR_APPEND(cpSearchString, strDir, XN_FILE_MAX_PATH, nRetVal); + XN_VALIDATE_STR_APPEND(cpSearchString, XN_FILE_DIR_SEP, XN_FILE_MAX_PATH, nRetVal); + XN_VALIDATE_STR_APPEND(cpSearchString, XN_SHARED_LIBRARY_PREFIX, XN_FILE_MAX_PATH, nRetVal); + XN_VALIDATE_STR_APPEND(cpSearchString, XN_DEVICE_FILE_PREFIX, XN_FILE_MAX_PATH, nRetVal); + XN_VALIDATE_STR_APPEND(cpSearchString, XN_FILE_ALL_WILDCARD, XN_FILE_MAX_PATH, nRetVal); + XN_VALIDATE_STR_APPEND(cpSearchString, XN_SHARED_LIBRARY_POSTFIX, XN_FILE_MAX_PATH, nRetVal); + + // Get a file list of Xiron devices + XnChar acsFileList[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES][XN_FILE_MAX_PATH]; + XnUInt32 nFileCount = 0; + + xnLogVerbose(XN_MASK_DEVICE_MANAGER, "Searching for %s...", cpSearchString); + nRetVal = xnOSGetFileList(cpSearchString, NULL, acsFileList, XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES, &nFileCount); + if ((nRetVal != XN_STATUS_OS_FILE_NOT_FOUND) && (nRetVal != XN_STATUS_OK)) + { + return (nRetVal); + } + + // now try to load each file + for (XnUInt32 nIndex = 0; nIndex < nFileCount; ++nIndex) + { + xnLogVerbose(XN_MASK_DEVICE_MANAGER, "Trying to load a device '%s'...", acsFileList[nIndex]); + nRetVal = XnDeviceManagerLoadDevice(acsFileList[nIndex], &g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_DEVICE_MANAGER, "'%s' is not a valid device: %s", acsFileList[nIndex], xnGetStatusString(nRetVal)); + } + else + { + xnLogInfo(XN_MASK_DEVICE_MANAGER, "device '%s' loaded.", acsFileList[nIndex]); + g_pDeviceManager->nDevicesCount++; + } + } + + return (XN_STATUS_OK); +} + +#else // no dynamic libs + +XnStatus XnDeviceManagerLoadAllDevices() +{ + XnStatus nRetVal = XN_STATUS_OK; + + #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) pDescriptor->Interface.name = XN_DEVICE_PROTO_NAME(name); + + XnDeviceDescriptor* pDescriptor = g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]; + + #define XN_DEVICE_EXPORT_PREFIX SensorV2_ + #include + #undef XN_DEVICE_EXPORT_PREFIX + + nRetVal = XnDeviceManagerUpdateDefinition(pDescriptor); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_DEVICE_MANAGER, "'SensorV2' is not a valid device: %s", xnGetStatusString(nRetVal)); + } + else + { + g_pDeviceManager->nDevicesCount++; + } + + XnDeviceDescriptor* pDescriptor = g_pDeviceManager->aDevices[g_pDeviceManager->nDevicesCount]; + + #define XN_DEVICE_EXPORT_PREFIX File_ + #include + #undef XN_DEVICE_EXPORT_PREFIX + + nRetVal = XnDeviceManagerUpdateDefinition(pDescriptor); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_DEVICE_MANAGER, "'SensorV2' is not a valid device: %s", xnGetStatusString(nRetVal)); + } + else + { + g_pDeviceManager->nDevicesCount++; + } + + #undef XN_DEVICE_INTERFACE_FUNCTION + + return (XN_STATUS_OK) +} + +#endif + +XnStatus XnDeviceManagerInit(const XnChar* strDevicesDir) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if device manager is already initialized + if (g_pDeviceManager != NULL) + { + return XN_STATUS_ALREADY_INIT; + } + + // allocate data + XN_VALIDATE_ALLOC(g_pDeviceManager, XnDeviceManagerData); + g_pDeviceManager->nDevicesCount = 0; + + // load devices + nRetVal = XnDeviceManagerLoadAllDevices(strDevicesDir); + XN_IS_STATUS_OK(nRetVal); + + // make sure we found at least one device + if (g_pDeviceManager->nDevicesCount == 0) + { + return (XN_STATUS_IO_NO_DEVICES); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceManagerShutdown() +{ +#ifdef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS + // unload all libraries + for (XnUInt32 i = 0; i < g_pDeviceManager->nDevicesCount; ++i) + { + xnOSFreeLibrary(g_pDeviceManager->aDevices[i].hLib); + } +#endif + + // check if device manager is initialized + if (g_pDeviceManager == NULL) + { + return XN_STATUS_NOT_INIT; + } + + // free data + XN_FREE_AND_NULL(g_pDeviceManager); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceManagerGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if device manager is initialized + if (g_pDeviceManager == NULL) + { + return XN_STATUS_NOT_INIT; + } + + // check count + XnUInt32 nArraySize = *pnCount; + + *pnCount = g_pDeviceManager->nDevicesCount; + + if (nArraySize < g_pDeviceManager->nDevicesCount) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + // copy definitions + for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) + { + aDeviceDefinitions[nIndex] = g_pDeviceManager->aDevices[nIndex].Definition; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceManagerGetDeviceByName(const XnChar* csName, XnDeviceDescriptor** ppDeviceDescriptor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if device manager is initialized + if (g_pDeviceManager == NULL) + { + return XN_STATUS_NOT_INIT; + } + + // special case: AUTO + if (strncmp(csName, XN_DEVICE_MANAGER_AUTO_NAME, strlen(XN_DEVICE_MANAGER_AUTO_NAME)) == 0) + { + for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) + { + // Get a pointer to the current device descriptor + XnDeviceDescriptor* pDescriptor = &g_pDeviceManager->aDevices[nIndex]; + + XnUInt32 nCount = 0; + nRetVal = pDescriptor->Interface.Enumerate(NULL, &nCount); + if (nCount > 0) + { + *ppDeviceDescriptor = pDescriptor; + return (XN_STATUS_OK); + } + } + } + else + { + // search by name + for (XnUInt32 nIndex = 0; nIndex < g_pDeviceManager->nDevicesCount; ++nIndex) + { + if (strcmp(g_pDeviceManager->aDevices[nIndex].Definition.cpName, csName) == 0) + { + *ppDeviceDescriptor = &g_pDeviceManager->aDevices[nIndex]; + return (XN_STATUS_OK); + } + } + } + + return (XN_STATUS_IO_DEVICE_NOT_FOUND); +} diff --git a/Source/XnDDK/XnDeviceManager.h b/Source/XnDDK/XnDeviceManager.h index 20be6dc..a6b470d 100644 --- a/Source/XnDDK/XnDeviceManager.h +++ b/Source/XnDDK/XnDeviceManager.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_MANAGER_H__ -#define __XN_DEVICE_MANAGER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnDeviceFunctionsTypedefs.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES 100 -/** The name of the auto scan device */ -#define XN_DEVICE_MANAGER_AUTO_NAME "Auto" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -/** -* Represents all the functions in the device interface. -*/ -typedef struct XnDeviceInterfaceFunctions { - #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) XN_DEVICE_TYPEDEF_NAME(name) name; - #include - #undef XN_DEVICE_INTERFACE_FUNCTION -} XnDeviceInterfaceFunctions; - -/** -* Represents a descriptor of a device. -*/ -typedef struct XnDeviceDescriptor -{ - XnDeviceDefinition Definition; - XnDeviceInterfaceFunctions Interface; - XN_LIB_HANDLE hLib; -} XnDeviceDescriptor; - -//--------------------------------------------------------------------------- -// Functions -//--------------------------------------------------------------------------- -XnStatus XnDeviceManagerInit(const XnChar* strDevicesDir); -XnStatus XnDeviceManagerShutdown(); -XnStatus XnDeviceManagerGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount); -XnStatus XnDeviceManagerGetDeviceByName(const XnChar* csName, XnDeviceDescriptor** ppDeviceDescriptor); - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_MANAGER_H__ +#define __XN_DEVICE_MANAGER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnDeviceFunctionsTypedefs.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES 100 +/** The name of the auto scan device */ +#define XN_DEVICE_MANAGER_AUTO_NAME "Auto" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +/** +* Represents all the functions in the device interface. +*/ +typedef struct XnDeviceInterfaceFunctions { + #define XN_DEVICE_INTERFACE_FUNCTION(name, sig) XN_DEVICE_TYPEDEF_NAME(name) name; + #include + #undef XN_DEVICE_INTERFACE_FUNCTION +} XnDeviceInterfaceFunctions; + +/** +* Represents a descriptor of a device. +*/ +typedef struct XnDeviceDescriptor +{ + XnDeviceDefinition Definition; + XnDeviceInterfaceFunctions Interface; + XN_LIB_HANDLE hLib; +} XnDeviceDescriptor; + +//--------------------------------------------------------------------------- +// Functions +//--------------------------------------------------------------------------- +XnStatus XnDeviceManagerInit(const XnChar* strDevicesDir); +XnStatus XnDeviceManagerShutdown(); +XnStatus XnDeviceManagerGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount); +XnStatus XnDeviceManagerGetDeviceByName(const XnChar* csName, XnDeviceDescriptor** ppDeviceDescriptor); + #endif //__XN_DEVICE_MANAGER_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnDeviceModule.cpp b/Source/XnDDK/XnDeviceModule.cpp index d577714..9d8d3b0 100644 --- a/Source/XnDDK/XnDeviceModule.cpp +++ b/Source/XnDDK/XnDeviceModule.cpp @@ -1,554 +1,554 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceModule.h" -#include -#include -#include -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDeviceModule::XnDeviceModule(const XnChar* strName) : - m_Lock(XN_MODULE_PROPERTY_LOCK, FALSE, strName), - m_hLockCS(NULL) -{ - strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); - m_Lock.UpdateSetCallback(SetLockStateCallback, this); -} - -XnDeviceModule::~XnDeviceModule() -{ - Free(); -} - -XnStatus XnDeviceModule::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = AddProperty(&m_Lock); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateCriticalSection(&m_hLockCS); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::Free() -{ - xnOSCloseCriticalSection(&m_hLockCS); - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::AddProperty(XnProperty* pProperty) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // make sure another property with this name doesn't exist - XnPropertiesHash::Iterator it = m_Properties.end(); - if (XN_STATUS_NO_MATCH != m_Properties.Find(pProperty->GetName(), it)) - return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; - - nRetVal = m_Properties.Set(pProperty->GetName(), pProperty); - XN_IS_STATUS_OK(nRetVal); - - pProperty->UpdateName(GetName(), pProperty->GetName()); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::AddProperties(XnProperty** apProperties, XnUInt32 nCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnUInt32 i = 0; i < nCount; ++i) - { - nRetVal = AddProperty(apProperties[i]); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::DoesPropertyExist(const XnChar* strName, XnBool* pbDoesExist) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - *pbDoesExist = FALSE; - - XnPropertiesHash::ConstIterator it = m_Properties.end(); - nRetVal = m_Properties.Find(strName, it); - if (nRetVal != XN_STATUS_NO_MATCH && nRetVal != XN_STATUS_OK) - { - return (nRetVal); - } - - *pbDoesExist = (nRetVal == XN_STATUS_OK); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::GetPropertyType(const XnChar* strName, XnPropertyType* pnType) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - *pnType = pProp->GetType(); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::GetPropertyImpl(const XnChar* Name, XnPropertyType Type, XnProperty** ppProperty) const -{ - *ppProperty = NULL; - - XnProperty* pProperty; - if (XN_STATUS_NO_MATCH == m_Properties.Get(Name, pProperty)) - { - return XN_STATUS_DEVICE_PROPERTY_DONT_EXIST; - } - - if (pProperty->GetType() != Type) - { - return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; - } - - *ppProperty = pProperty; - return XN_STATUS_OK; -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnProperty **ppProperty) const -{ - XnProperty* pProperty; - if (XN_STATUS_NO_MATCH == m_Properties.Get(Name, pProperty)) - { - return XN_STATUS_DEVICE_PROPERTY_DONT_EXIST; - } - - *ppProperty = pProperty; - - return XN_STATUS_OK; -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnUInt64* pnValue) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnIntProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->GetValue(pnValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnDouble* pdValue) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnRealProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->GetValue(pdValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnChar* csValue) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStringProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->GetValue(csValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); - -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnGeneralProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->GetValue(gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::SetProperty(const XnChar* strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnIntProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->SetValue(nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::SetProperty(const XnChar* strName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnRealProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->SetValue(dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::SetProperty(const XnChar* strName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStringProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->SetValue(strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::SetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnGeneralProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->SetValue(gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnIntProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->UnsafeUpdateValue(nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnRealProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->UnsafeUpdateValue(dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStringProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->UnsafeUpdateValue(strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnGeneralProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->UnsafeUpdateValue(gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::RegisterForOnPropertyValueChanged(const XnChar* strName, XnProperty::OnValueChangedHandler pFunc, void* pCookie, XnCallbackHandle* pHandle) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->OnChangeEvent().Register(pFunc, pCookie, pHandle); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnregisterFromOnPropertyValueChanged(const XnChar* strName, XnCallbackHandle hCallback) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pProp; - nRetVal = GetProperty(strName, &pProp); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->OnChangeEvent().Unregister(hCallback); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnIntProperty **ppIntProperty) const -{ - return GetPropertyImpl(Name, XN_PROPERTY_TYPE_INTEGER, (XnProperty**)ppIntProperty); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnRealProperty **ppRealProperty) const -{ - return GetPropertyImpl(Name, XN_PROPERTY_TYPE_REAL, (XnProperty**)ppRealProperty); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnStringProperty **ppStringProperty) const -{ - return GetPropertyImpl(Name, XN_PROPERTY_TYPE_STRING, (XnProperty**)ppStringProperty); -} - -XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnGeneralProperty **ppPtrProperty) const -{ - return GetPropertyImpl(Name, XN_PROPERTY_TYPE_GENERAL, (XnProperty**)ppPtrProperty); -} - -XnStatus XnDeviceModule::GetAllProperties(XnPropertySet* pSet) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - // add the module - nRetVal = XnPropertySetAddModule(pSet, GetName()); - XN_IS_STATUS_OK(nRetVal); - - // now add all properties - for (XnPropertiesHash::ConstIterator it = m_Properties.begin(); it != m_Properties.end(); ++it) - { - XnProperty* pProperty = it.Value(); - - if (pProperty->IsActual()) - { - nRetVal = pProperty->AddToPropertySet(pSet); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* strSectionName /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (strSectionName == NULL) - { - strSectionName = GetName(); - } - - xnLogVerbose(XN_MASK_DDK, "Configuring module '%s' from section '%s' in file '%s'...", GetName(), strSectionName, csINIFilePath); - - for (XnPropertiesHash::Iterator it = m_Properties.begin(); it != m_Properties.end(); ++it) - { - XnProperty* pProp = it.Value(); - - // only read writable properties - if (!pProp->IsReadOnly()) - { - nRetVal = pProp->ReadValueFromFile(csINIFilePath, strSectionName); - XN_IS_STATUS_OK(nRetVal); - } - } - - xnLogInfo(XN_MASK_DDK, "Module '%s' configuration was loaded from file.", GetName()); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::BatchConfig(const XnActualPropertiesHash& props) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) - { - XnProperty* pRequestProp = it.Value(); - switch (pRequestProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; - nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; - nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; - nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; - nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); - } // type switch - } // props loop - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::UnsafeBatchConfig(const XnActualPropertiesHash& props) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) - { - XnProperty* pRequestProp = it.Value(); - switch (pRequestProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; - nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; - nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; - nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; - nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); - } // type switch - } // props loop - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModule::SetLockState(XnBool bLocked) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (bLocked && m_Lock.GetValue() == TRUE) - { - return XN_STATUS_NODE_IS_LOCKED; - } - - xnOSEnterCriticalSection(&m_hLockCS); - - // check again - if (bLocked && m_Lock.GetValue() == TRUE) - { - xnOSLeaveCriticalSection(&m_hLockCS); - return XN_STATUS_NODE_IS_LOCKED; - } - - nRetVal = m_Lock.UnsafeUpdateValue(bLocked); - xnOSLeaveCriticalSection(&m_hLockCS); - - return (nRetVal); -} - -XnStatus XnDeviceModule::SetLockStateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceModule* pThis = (XnDeviceModule*)pCookie; - return pThis->SetLockState(nValue != FALSE); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceModule.h" +#include +#include +#include +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDeviceModule::XnDeviceModule(const XnChar* strName) : + m_Lock(XN_MODULE_PROPERTY_LOCK, FALSE, strName), + m_hLockCS(NULL) +{ + strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); + m_Lock.UpdateSetCallback(SetLockStateCallback, this); +} + +XnDeviceModule::~XnDeviceModule() +{ + Free(); +} + +XnStatus XnDeviceModule::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = AddProperty(&m_Lock); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateCriticalSection(&m_hLockCS); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::Free() +{ + xnOSCloseCriticalSection(&m_hLockCS); + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::AddProperty(XnProperty* pProperty) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // make sure another property with this name doesn't exist + XnPropertiesHash::Iterator it = m_Properties.end(); + if (XN_STATUS_NO_MATCH != m_Properties.Find(pProperty->GetName(), it)) + return XN_STATUS_DEVICE_PROPERTY_ALREADY_EXISTS; + + nRetVal = m_Properties.Set(pProperty->GetName(), pProperty); + XN_IS_STATUS_OK(nRetVal); + + pProperty->UpdateName(GetName(), pProperty->GetName()); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::AddProperties(XnProperty** apProperties, XnUInt32 nCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnUInt32 i = 0; i < nCount; ++i) + { + nRetVal = AddProperty(apProperties[i]); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::DoesPropertyExist(const XnChar* strName, XnBool* pbDoesExist) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + *pbDoesExist = FALSE; + + XnPropertiesHash::ConstIterator it = m_Properties.end(); + nRetVal = m_Properties.Find(strName, it); + if (nRetVal != XN_STATUS_NO_MATCH && nRetVal != XN_STATUS_OK) + { + return (nRetVal); + } + + *pbDoesExist = (nRetVal == XN_STATUS_OK); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::GetPropertyType(const XnChar* strName, XnPropertyType* pnType) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + *pnType = pProp->GetType(); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::GetPropertyImpl(const XnChar* Name, XnPropertyType Type, XnProperty** ppProperty) const +{ + *ppProperty = NULL; + + XnProperty* pProperty; + if (XN_STATUS_NO_MATCH == m_Properties.Get(Name, pProperty)) + { + return XN_STATUS_DEVICE_PROPERTY_DONT_EXIST; + } + + if (pProperty->GetType() != Type) + { + return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; + } + + *ppProperty = pProperty; + return XN_STATUS_OK; +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnProperty **ppProperty) const +{ + XnProperty* pProperty; + if (XN_STATUS_NO_MATCH == m_Properties.Get(Name, pProperty)) + { + return XN_STATUS_DEVICE_PROPERTY_DONT_EXIST; + } + + *ppProperty = pProperty; + + return XN_STATUS_OK; +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnUInt64* pnValue) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnIntProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->GetValue(pnValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnDouble* pdValue) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnRealProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->GetValue(pdValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* strName, XnChar* csValue) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStringProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->GetValue(csValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); + +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnGeneralProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->GetValue(gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::SetProperty(const XnChar* strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnIntProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->SetValue(nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::SetProperty(const XnChar* strName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnRealProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->SetValue(dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::SetProperty(const XnChar* strName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStringProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->SetValue(strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::SetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnGeneralProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->SetValue(gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnIntProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->UnsafeUpdateValue(nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnRealProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->UnsafeUpdateValue(dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStringProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->UnsafeUpdateValue(strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnsafeUpdateProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnGeneralProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->UnsafeUpdateValue(gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::RegisterForOnPropertyValueChanged(const XnChar* strName, XnProperty::OnValueChangedHandler pFunc, void* pCookie, XnCallbackHandle* pHandle) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->OnChangeEvent().Register(pFunc, pCookie, pHandle); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnregisterFromOnPropertyValueChanged(const XnChar* strName, XnCallbackHandle hCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pProp; + nRetVal = GetProperty(strName, &pProp); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->OnChangeEvent().Unregister(hCallback); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnIntProperty **ppIntProperty) const +{ + return GetPropertyImpl(Name, XN_PROPERTY_TYPE_INTEGER, (XnProperty**)ppIntProperty); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnRealProperty **ppRealProperty) const +{ + return GetPropertyImpl(Name, XN_PROPERTY_TYPE_REAL, (XnProperty**)ppRealProperty); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnStringProperty **ppStringProperty) const +{ + return GetPropertyImpl(Name, XN_PROPERTY_TYPE_STRING, (XnProperty**)ppStringProperty); +} + +XnStatus XnDeviceModule::GetProperty(const XnChar* Name, XnGeneralProperty **ppPtrProperty) const +{ + return GetPropertyImpl(Name, XN_PROPERTY_TYPE_GENERAL, (XnProperty**)ppPtrProperty); +} + +XnStatus XnDeviceModule::GetAllProperties(XnPropertySet* pSet) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + // add the module + nRetVal = XnPropertySetAddModule(pSet, GetName()); + XN_IS_STATUS_OK(nRetVal); + + // now add all properties + for (XnPropertiesHash::ConstIterator it = m_Properties.begin(); it != m_Properties.end(); ++it) + { + XnProperty* pProperty = it.Value(); + + if (pProperty->IsActual()) + { + nRetVal = pProperty->AddToPropertySet(pSet); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* strSectionName /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (strSectionName == NULL) + { + strSectionName = GetName(); + } + + xnLogVerbose(XN_MASK_DDK, "Configuring module '%s' from section '%s' in file '%s'...", GetName(), strSectionName, csINIFilePath); + + for (XnPropertiesHash::Iterator it = m_Properties.begin(); it != m_Properties.end(); ++it) + { + XnProperty* pProp = it.Value(); + + // only read writable properties + if (!pProp->IsReadOnly()) + { + nRetVal = pProp->ReadValueFromFile(csINIFilePath, strSectionName); + XN_IS_STATUS_OK(nRetVal); + } + } + + xnLogInfo(XN_MASK_DDK, "Module '%s' configuration was loaded from file.", GetName()); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::BatchConfig(const XnActualPropertiesHash& props) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) + { + XnProperty* pRequestProp = it.Value(); + switch (pRequestProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; + nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; + nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; + nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; + nRetVal = SetProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); + } // type switch + } // props loop + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::UnsafeBatchConfig(const XnActualPropertiesHash& props) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) + { + XnProperty* pRequestProp = it.Value(); + switch (pRequestProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; + nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; + nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; + nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; + nRetVal = UnsafeUpdateProperty(pProp->GetName(), pProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); + } // type switch + } // props loop + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModule::SetLockState(XnBool bLocked) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (bLocked && m_Lock.GetValue() == TRUE) + { + return XN_STATUS_NODE_IS_LOCKED; + } + + xnOSEnterCriticalSection(&m_hLockCS); + + // check again + if (bLocked && m_Lock.GetValue() == TRUE) + { + xnOSLeaveCriticalSection(&m_hLockCS); + return XN_STATUS_NODE_IS_LOCKED; + } + + nRetVal = m_Lock.UnsafeUpdateValue(bLocked); + xnOSLeaveCriticalSection(&m_hLockCS); + + return (nRetVal); +} + +XnStatus XnDeviceModule::SetLockStateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceModule* pThis = (XnDeviceModule*)pCookie; + return pThis->SetLockState(nValue != FALSE); +} diff --git a/Source/XnDDK/XnDeviceModule.h b/Source/XnDDK/XnDeviceModule.h index 45fbd92..d0eca73 100644 --- a/Source/XnDDK/XnDeviceModule.h +++ b/Source/XnDDK/XnDeviceModule.h @@ -1,122 +1,122 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_MODULE_H__ -#define __XN_DEVICE_MODULE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* Holds a set of properties related to a specific module. -*/ -class XN_DDK_CPP_API XnDeviceModule -{ -public: - XnDeviceModule(const XnChar* strName); - virtual ~XnDeviceModule(); - - virtual XnStatus Init(); - virtual XnStatus Free(); - - inline const XnChar* GetName() const { return m_strName; } - - XnStatus AddProperty(XnProperty* pProperty); - XnStatus AddProperties(XnProperty** apProperties, XnUInt32 nCount); - - XnStatus DoesPropertyExist(const XnChar* strName, XnBool* pbDoesExist) const; - XnStatus GetPropertyType(const XnChar* strName, XnPropertyType* pnType) const; - - XnStatus GetProperty(const XnChar* strName, XnProperty** ppProperty) const; - - virtual XnStatus GetProperty(const XnChar* strName, XnUInt64* pnValue) const; - virtual XnStatus GetProperty(const XnChar* strName, XnDouble* pdValue) const; - virtual XnStatus GetProperty(const XnChar* strName, XnChar* csValue) const; - virtual XnStatus GetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) const; - - virtual XnStatus SetProperty(const XnChar* strName, XnUInt64 nValue); - virtual XnStatus SetProperty(const XnChar* strName, XnDouble dValue); - virtual XnStatus SetProperty(const XnChar* strName, const XnChar* strValue); - virtual XnStatus SetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue); - - virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, XnUInt64 nValue); - virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, XnDouble dValue); - virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, const XnChar* strValue); - virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, const XnGeneralBuffer& gbValue); - - XnStatus GetAllProperties(XnPropertySet* pSet) const; - - XnStatus RegisterForOnPropertyValueChanged(const XnChar* strName, XnProperty::OnValueChangedHandler pFunc, void* pCookie, XnCallbackHandle* pHandle); - XnStatus UnregisterFromOnPropertyValueChanged(const XnChar* strName, XnCallbackHandle hCallback); - - /** - * Reads values for all properties in module from an INI file. - */ - XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* strSectionName = NULL); - - virtual XnStatus BatchConfig(const XnActualPropertiesHash& props); - virtual XnStatus UnsafeBatchConfig(const XnActualPropertiesHash& props); - - XnStatus GetProperty(const XnChar* strName, XnIntProperty** ppIntProperty) const; - XnStatus GetProperty(const XnChar* strName, XnRealProperty** ppRealProperty) const; - XnStatus GetProperty(const XnChar* strName, XnStringProperty** ppStringProperty) const; - XnStatus GetProperty(const XnChar* strName, XnGeneralProperty** ppGeneralProperty) const; - -private: - XnStatus GetPropertyImpl(const XnChar* Name, XnPropertyType Type, XnProperty** ppProperty) const; - - XnStatus SetLockState(XnBool bLocked); - - static XnStatus XN_CALLBACK_TYPE SetLockStateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; - - XnPropertiesHash m_Properties; - XnActualIntProperty m_Lock; - XN_CRITICAL_SECTION_HANDLE m_hLockCS; -}; - -#define XN_VALIDATE_ADD_PROPERTIES(pModule, ...) \ - do { \ - XnProperty* _aProps[] = { __VA_ARGS__ }; \ - XnStatus _nRetVal = (pModule)->AddProperties(_aProps, sizeof(_aProps)/sizeof(XnProperty*)); \ - XN_IS_STATUS_OK(_nRetVal); \ - } while (0) - - -#endif //__XN_DEVICE_MODULE_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_MODULE_H__ +#define __XN_DEVICE_MODULE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* Holds a set of properties related to a specific module. +*/ +class XN_DDK_CPP_API XnDeviceModule +{ +public: + XnDeviceModule(const XnChar* strName); + virtual ~XnDeviceModule(); + + virtual XnStatus Init(); + virtual XnStatus Free(); + + inline const XnChar* GetName() const { return m_strName; } + + XnStatus AddProperty(XnProperty* pProperty); + XnStatus AddProperties(XnProperty** apProperties, XnUInt32 nCount); + + XnStatus DoesPropertyExist(const XnChar* strName, XnBool* pbDoesExist) const; + XnStatus GetPropertyType(const XnChar* strName, XnPropertyType* pnType) const; + + XnStatus GetProperty(const XnChar* strName, XnProperty** ppProperty) const; + + virtual XnStatus GetProperty(const XnChar* strName, XnUInt64* pnValue) const; + virtual XnStatus GetProperty(const XnChar* strName, XnDouble* pdValue) const; + virtual XnStatus GetProperty(const XnChar* strName, XnChar* csValue) const; + virtual XnStatus GetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue) const; + + virtual XnStatus SetProperty(const XnChar* strName, XnUInt64 nValue); + virtual XnStatus SetProperty(const XnChar* strName, XnDouble dValue); + virtual XnStatus SetProperty(const XnChar* strName, const XnChar* strValue); + virtual XnStatus SetProperty(const XnChar* strName, const XnGeneralBuffer& gbValue); + + virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, XnUInt64 nValue); + virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, XnDouble dValue); + virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, const XnChar* strValue); + virtual XnStatus UnsafeUpdateProperty(const XnChar* strName, const XnGeneralBuffer& gbValue); + + XnStatus GetAllProperties(XnPropertySet* pSet) const; + + XnStatus RegisterForOnPropertyValueChanged(const XnChar* strName, XnProperty::OnValueChangedHandler pFunc, void* pCookie, XnCallbackHandle* pHandle); + XnStatus UnregisterFromOnPropertyValueChanged(const XnChar* strName, XnCallbackHandle hCallback); + + /** + * Reads values for all properties in module from an INI file. + */ + XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* strSectionName = NULL); + + virtual XnStatus BatchConfig(const XnActualPropertiesHash& props); + virtual XnStatus UnsafeBatchConfig(const XnActualPropertiesHash& props); + + XnStatus GetProperty(const XnChar* strName, XnIntProperty** ppIntProperty) const; + XnStatus GetProperty(const XnChar* strName, XnRealProperty** ppRealProperty) const; + XnStatus GetProperty(const XnChar* strName, XnStringProperty** ppStringProperty) const; + XnStatus GetProperty(const XnChar* strName, XnGeneralProperty** ppGeneralProperty) const; + +private: + XnStatus GetPropertyImpl(const XnChar* Name, XnPropertyType Type, XnProperty** ppProperty) const; + + XnStatus SetLockState(XnBool bLocked); + + static XnStatus XN_CALLBACK_TYPE SetLockStateCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; + + XnPropertiesHash m_Properties; + XnActualIntProperty m_Lock; + XN_CRITICAL_SECTION_HANDLE m_hLockCS; +}; + +#define XN_VALIDATE_ADD_PROPERTIES(pModule, ...) \ + do { \ + XnProperty* _aProps[] = { __VA_ARGS__ }; \ + XnStatus _nRetVal = (pModule)->AddProperties(_aProps, sizeof(_aProps)/sizeof(XnProperty*)); \ + XN_IS_STATUS_OK(_nRetVal); \ + } while (0) + + +#endif //__XN_DEVICE_MODULE_H__ diff --git a/Source/XnDDK/XnDeviceModuleHolder.cpp b/Source/XnDDK/XnDeviceModuleHolder.cpp index 260fdc1..6b40208 100644 --- a/Source/XnDDK/XnDeviceModuleHolder.cpp +++ b/Source/XnDDK/XnDeviceModuleHolder.cpp @@ -1,225 +1,225 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#include "XnDeviceModuleHolder.h" -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" - -XnDeviceModuleHolder::XnDeviceModuleHolder(XnDeviceModule* pModule, XnBool bAllowNewProps /* = FALSE */) : - m_pModule(pModule), - m_bAllowNewProps(bAllowNewProps) -{} - -XnDeviceModuleHolder::~XnDeviceModuleHolder() -{ - XnDeviceModuleHolder::Free(); -} - -XnStatus XnDeviceModuleHolder::Init(const XnActualPropertiesHash* pInitialValues) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pModule->Init(); - XN_IS_STATUS_OK(nRetVal); - - if (pInitialValues != NULL) - { - if (m_bAllowNewProps) - { - // clone all properties and add them to the device - nRetVal = UnsafeSetProperties(*pInitialValues); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nRetVal = m_pModule->BatchConfig(*pInitialValues); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModuleHolder::Free() -{ - // free all allocated properties (we assume we're part of destruction, so that no need to remove - // them from Module). - while (!m_Allocated.IsEmpty()) - { - XnProperty* pProp = *(m_Allocated.begin()); - m_Allocated.Remove(m_Allocated.begin()); - XN_DELETE(pProp); - } - - return XN_STATUS_OK; -} - -XnStatus XnDeviceModuleHolder::UnsafeSetProperties(const XnActualPropertiesHash& props) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) - { - XnProperty* pRequestProp = it.Value(); - XnProperty* pProp = NULL; - - // check if property already exist - nRetVal = m_pModule->GetProperty(pRequestProp->GetName(), &pProp); - if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) - { - // property doesn't exist. create it now - nRetVal = CreateProperty(pRequestProp); - XN_IS_STATUS_OK(nRetVal); - } - else if (nRetVal == XN_STATUS_OK) - { - // property exists. Change its value - nRetVal = UnsafeSetProperty(pRequestProp, pProp); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // error - return (nRetVal); - } - - } // props loop - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceModuleHolder::CreateProperty(XnProperty* pRequestProp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProperty* pNewProp = NULL; - - switch (pRequestProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; - XN_VALIDATE_NEW(pNewProp, XnActualIntProperty, pProp->GetName(), pProp->GetValue()); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; - XN_VALIDATE_NEW(pNewProp, XnActualRealProperty, pProp->GetName(), pProp->GetValue()); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; - XN_VALIDATE_NEW(pNewProp, XnActualStringProperty, pProp->GetName(), pProp->GetValue()); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; - - // create new buffer - XnGeneralBuffer gbNew; - nRetVal = XnGeneralBufferAlloc(&gbNew, pProp->GetValue().nDataSize); - XN_IS_STATUS_OK(nRetVal); - - // copy content - xnOSMemCopy(gbNew.pData, pProp->GetValue().pData, pProp->GetValue().nDataSize); - - XnActualGeneralProperty* pNewGeneralProp = NULL; - XN_VALIDATE_NEW(pNewGeneralProp, XnActualGeneralProperty, pProp->GetName(), gbNew); - pNewGeneralProp->SetAsBufferOwner(TRUE); - pNewProp = pNewGeneralProp; - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); - } // switch - - // add the property to the module - nRetVal = m_pModule->AddProperty(pNewProp); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pNewProp); - return (nRetVal); - } - - // and add it to the list of allocated ones (so we'll delete it afterwards) - m_Allocated.AddLast(pNewProp); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceModuleHolder::UnsafeSetProperty(const XnProperty* pRequest, XnProperty* pProp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (pRequest->GetType() != pProp->GetType()) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_BAD_TYPE, XN_MASK_DDK, "Property '%s' has the wrong type!", pRequest->GetName()); - } - - switch (pRequest->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pActualRequest = (XnActualIntProperty*)pRequest; - XnActualIntProperty* pActualProp = (XnActualIntProperty*)pProp; - nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pActualRequest = (XnActualRealProperty*)pRequest; - XnActualRealProperty* pActualProp = (XnActualRealProperty*)pProp; - nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pActualRequest = (XnActualStringProperty*)pRequest; - XnActualStringProperty* pActualProp = (XnActualStringProperty*)pProp; - nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pActualRequest = (XnActualGeneralProperty*)pRequest; - XnActualGeneralProperty* pActualProp = (XnActualGeneralProperty*)pProp; - nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequest->GetType()); - } // switch - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#include "XnDeviceModuleHolder.h" +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" + +XnDeviceModuleHolder::XnDeviceModuleHolder(XnDeviceModule* pModule, XnBool bAllowNewProps /* = FALSE */) : + m_pModule(pModule), + m_bAllowNewProps(bAllowNewProps) +{} + +XnDeviceModuleHolder::~XnDeviceModuleHolder() +{ + XnDeviceModuleHolder::Free(); +} + +XnStatus XnDeviceModuleHolder::Init(const XnActualPropertiesHash* pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pModule->Init(); + XN_IS_STATUS_OK(nRetVal); + + if (pInitialValues != NULL) + { + if (m_bAllowNewProps) + { + // clone all properties and add them to the device + nRetVal = UnsafeSetProperties(*pInitialValues); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nRetVal = m_pModule->BatchConfig(*pInitialValues); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModuleHolder::Free() +{ + // free all allocated properties (we assume we're part of destruction, so that no need to remove + // them from Module). + while (!m_Allocated.IsEmpty()) + { + XnProperty* pProp = *(m_Allocated.begin()); + m_Allocated.Remove(m_Allocated.begin()); + XN_DELETE(pProp); + } + + return XN_STATUS_OK; +} + +XnStatus XnDeviceModuleHolder::UnsafeSetProperties(const XnActualPropertiesHash& props) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnActualPropertiesHash::ConstIterator it = props.begin(); it != props.end(); ++it) + { + XnProperty* pRequestProp = it.Value(); + XnProperty* pProp = NULL; + + // check if property already exist + nRetVal = m_pModule->GetProperty(pRequestProp->GetName(), &pProp); + if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) + { + // property doesn't exist. create it now + nRetVal = CreateProperty(pRequestProp); + XN_IS_STATUS_OK(nRetVal); + } + else if (nRetVal == XN_STATUS_OK) + { + // property exists. Change its value + nRetVal = UnsafeSetProperty(pRequestProp, pProp); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // error + return (nRetVal); + } + + } // props loop + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceModuleHolder::CreateProperty(XnProperty* pRequestProp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProperty* pNewProp = NULL; + + switch (pRequestProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pProp = (XnActualIntProperty*)pRequestProp; + XN_VALIDATE_NEW(pNewProp, XnActualIntProperty, pProp->GetName(), pProp->GetValue()); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pProp = (XnActualRealProperty*)pRequestProp; + XN_VALIDATE_NEW(pNewProp, XnActualRealProperty, pProp->GetName(), pProp->GetValue()); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pProp = (XnActualStringProperty*)pRequestProp; + XN_VALIDATE_NEW(pNewProp, XnActualStringProperty, pProp->GetName(), pProp->GetValue()); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pRequestProp; + + // create new buffer + XnGeneralBuffer gbNew; + nRetVal = XnGeneralBufferAlloc(&gbNew, pProp->GetValue().nDataSize); + XN_IS_STATUS_OK(nRetVal); + + // copy content + xnOSMemCopy(gbNew.pData, pProp->GetValue().pData, pProp->GetValue().nDataSize); + + XnActualGeneralProperty* pNewGeneralProp = NULL; + XN_VALIDATE_NEW(pNewGeneralProp, XnActualGeneralProperty, pProp->GetName(), gbNew); + pNewGeneralProp->SetAsBufferOwner(TRUE); + pNewProp = pNewGeneralProp; + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequestProp->GetType()); + } // switch + + // add the property to the module + nRetVal = m_pModule->AddProperty(pNewProp); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pNewProp); + return (nRetVal); + } + + // and add it to the list of allocated ones (so we'll delete it afterwards) + m_Allocated.AddLast(pNewProp); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceModuleHolder::UnsafeSetProperty(const XnProperty* pRequest, XnProperty* pProp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (pRequest->GetType() != pProp->GetType()) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_BAD_TYPE, XN_MASK_DDK, "Property '%s' has the wrong type!", pRequest->GetName()); + } + + switch (pRequest->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pActualRequest = (XnActualIntProperty*)pRequest; + XnActualIntProperty* pActualProp = (XnActualIntProperty*)pProp; + nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pActualRequest = (XnActualRealProperty*)pRequest; + XnActualRealProperty* pActualProp = (XnActualRealProperty*)pProp; + nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pActualRequest = (XnActualStringProperty*)pRequest; + XnActualStringProperty* pActualProp = (XnActualStringProperty*)pProp; + nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pActualRequest = (XnActualGeneralProperty*)pRequest; + XnActualGeneralProperty* pActualProp = (XnActualGeneralProperty*)pProp; + nRetVal = pActualProp->UnsafeUpdateValue(pActualRequest->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d\n", pRequest->GetType()); + } // switch + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnDeviceModuleHolder.h b/Source/XnDDK/XnDeviceModuleHolder.h index 3e0447b..b4a50a8 100644 --- a/Source/XnDDK/XnDeviceModuleHolder.h +++ b/Source/XnDDK/XnDeviceModuleHolder.h @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_DEVICE_MODULE_HOLDER_H__ -#define __XN_DEVICE_MODULE_HOLDER_H__ - -#include "XnActualPropertiesHash.h" -#include "XnDeviceModule.h" - -class XN_DDK_CPP_API XnDeviceModuleHolder -{ -public: - /** - * Creates a new module holder. - * - * @param pModule [in] The actual module. - * @param bAllowNewProps [in] When TRUE, Init() method will create non-existing properties. - */ - XnDeviceModuleHolder(XnDeviceModule* pModule, XnBool bAllowNewProps = FALSE); - virtual ~XnDeviceModuleHolder(); - - virtual XnStatus Init(const XnActualPropertiesHash* pInitialValues); - - inline XnDeviceModule* GetModule() const { return m_pModule; } - -protected: - virtual XnStatus Free(); - -private: - XnStatus UnsafeSetProperties(const XnActualPropertiesHash& props); - XnStatus CreateProperty(XnProperty* pRequestProp); - XnStatus UnsafeSetProperty(const XnProperty* pRequest, XnProperty* pProp); - - XnDeviceModule* m_pModule; - XnPropertiesList m_Allocated; - XnBool m_bAllowNewProps; -}; - -XN_DECLARE_LIST_DECL(XN_DDK_CPP_API, XnDeviceModuleHolder*, XnDeviceModuleHolderList) - - -#endif //__XN_DEVICE_MODULE_HOLDER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_DEVICE_MODULE_HOLDER_H__ +#define __XN_DEVICE_MODULE_HOLDER_H__ + +#include "XnActualPropertiesHash.h" +#include "XnDeviceModule.h" + +class XN_DDK_CPP_API XnDeviceModuleHolder +{ +public: + /** + * Creates a new module holder. + * + * @param pModule [in] The actual module. + * @param bAllowNewProps [in] When TRUE, Init() method will create non-existing properties. + */ + XnDeviceModuleHolder(XnDeviceModule* pModule, XnBool bAllowNewProps = FALSE); + virtual ~XnDeviceModuleHolder(); + + virtual XnStatus Init(const XnActualPropertiesHash* pInitialValues); + + inline XnDeviceModule* GetModule() const { return m_pModule; } + +protected: + virtual XnStatus Free(); + +private: + XnStatus UnsafeSetProperties(const XnActualPropertiesHash& props); + XnStatus CreateProperty(XnProperty* pRequestProp); + XnStatus UnsafeSetProperty(const XnProperty* pRequest, XnProperty* pProp); + + XnDeviceModule* m_pModule; + XnPropertiesList m_Allocated; + XnBool m_bAllowNewProps; +}; + +XN_DECLARE_LIST_DECL(XN_DDK_CPP_API, XnDeviceModuleHolder*, XnDeviceModuleHolderList) + + +#endif //__XN_DEVICE_MODULE_HOLDER_H__ diff --git a/Source/XnDDK/XnDeviceProxy.cpp b/Source/XnDDK/XnDeviceProxy.cpp index 23ef5a9..439154f 100644 --- a/Source/XnDDK/XnDeviceProxy.cpp +++ b/Source/XnDDK/XnDeviceProxy.cpp @@ -1,632 +1,632 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnDeviceManager.h" -#include -#include -#include "XnDeviceInterfaceAdapter.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEVICE_PROXY_NAME "Proxy" -#define XN_DEVICE_PROXY_DESCRIPTION "Xiron Proxy Device" -#define XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR ";" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnDeviceProxyDeviceHandle -{ - XnDeviceDescriptor* pDesc; - XnDeviceHandle ActualDevice; -} XnDeviceProxyDeviceHandle; - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -/** Stores a hash of streamoutput objects to their creating device name. */ -XnHash g_StreamOutputHash; - -//--------------------------------------------------------------------------- -// XnDeviceProxy functions -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnDeviceProxyGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // take definitions - return XnDeviceManagerGetDeviceList(aDeviceDefinitions, pnCount); -} - -XN_DDK_API XnStatus XnDeviceProxyEnumerateDeviceByName(const XnChar* csDeviceName, XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get device interface - XnDeviceDescriptor* pDescriptor = NULL; - nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); - XN_IS_STATUS_OK(nRetVal); - - // enumerate - nRetVal = pDescriptor->Interface.Enumerate(aConnectionStrings, pnCount); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDeviceProxyCreateDeviceByName(const XnChar* csDeviceName, XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get device interface - XnDeviceDescriptor* pDescriptor = NULL; - nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); - XN_IS_STATUS_OK(nRetVal); - - // now create the actual device - XnDeviceHandle ActualDevice; - nRetVal = pDescriptor->Interface.Create(&ActualDevice, pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - // create our handle - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)xnOSMalloc(sizeof(XnDeviceProxyDeviceHandle)); - if (pHandle == NULL) - { - pDescriptor->Interface.Destroy(&ActualDevice); - return XN_STATUS_ALLOC_FAILED; - } - - pHandle->ActualDevice = ActualDevice; - pHandle->pDesc = pDescriptor; - - // and give it to user - *pDeviceHandle = pHandle; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDeviceProxyCreateDeviceByINIFile(const XnChar* strIniFileName, const XnChar* strSectionName, XnDeviceHandle* pDeviceHandle, const XnPropertySet* pInitialValues /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar cpDeviceName[XN_INI_MAX_LEN]; - XnChar cpMode[XN_INI_MAX_LEN]; - XnChar cpConnectionString[XN_INI_MAX_LEN]; - XnChar cpSharing[XN_INI_MAX_LEN]; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(strIniFileName); - XN_VALIDATE_INPUT_PTR(strSectionName); - XN_VALIDATE_OUTPUT_PTR(pDeviceHandle); - - XnDeviceConfig config; - config.cpConnectionString = cpConnectionString; - config.SharingMode = XN_DEVICE_EXCLUSIVE; - - // Read the device name, mode and connection string from the INI file into a temp strings - XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "Name", cpDeviceName, XN_INI_MAX_LEN, nRetVal); - XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "Mode", cpMode, XN_INI_MAX_LEN, nRetVal); - XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "ConnectionString", cpConnectionString, XN_INI_MAX_LEN, nRetVal); - - // Read optional parameters - if (XN_STATUS_OK == xnOSReadStringFromINI(strIniFileName, strSectionName, "Sharing", cpSharing, XN_INI_MAX_LEN)) - { - if (strcmp(cpSharing, "Exclusive") == 0) - { - config.SharingMode = XN_DEVICE_EXCLUSIVE; - } - else if (strcmp(cpSharing, "Shared") == 0) - { - config.SharingMode = XN_DEVICE_SHARED; - } - else - { - return (XN_STATUS_IO_DEVICE_INVALID_SHARING); - } - } - - if (strcmp(cpMode, "Read") == 0) - { - config.DeviceMode = XN_DEVICE_MODE_READ; - } - else if (strcmp(cpMode, "Write") == 0) - { - config.DeviceMode = XN_DEVICE_MODE_WRITE; - } - else - { - return (XN_STATUS_IO_DEVICE_INVALID_MODE); - } - - config.pInitialValues = pInitialValues; - - nRetVal = XnDeviceProxyCreateDeviceByName(cpDeviceName, pDeviceHandle, &config); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDeviceProxyDestroyStreamOutputByName(const XnChar* csDeviceName, XnStreamData** ppStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(csDeviceName); - XN_VALIDATE_INPUT_PTR(ppStreamOutput); - - // get device interface - XnDeviceDescriptor* pDescriptor = NULL; - nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pDescriptor->Interface.DestroyStreamData(ppStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnDeviceProxyGetDeviceName(XnDeviceHandle DeviceHandle, XnChar* csDeviceName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(DeviceHandle); - - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - nRetVal = xnOSStrCopy(csDeviceName, pHandle->pDesc->Definition.cpName, XN_DEVICE_MAX_STRING_LENGTH); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -//--------------------------------------------------------------------------- -// Device Interface implementation -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetDefinition)(XnDeviceDefinition* pDeviceDefinition) -{ - XN_VALIDATE_INPUT_PTR(pDeviceDefinition); - - pDeviceDefinition->cpName = XN_DEVICE_PROXY_NAME; - pDeviceDefinition->cpDescription = XN_DEVICE_PROXY_DESCRIPTION; - pDeviceDefinition->nMajorVersion = XN_PS_MAJOR_VERSION; - pDeviceDefinition->nMinorVersion = XN_PS_MINOR_VERSION; - pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Enumerate)(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(aConnectionStrings); - XN_VALIDATE_INPUT_PTR(pnCount); - - // take all loaded devices - XnDeviceDefinition aDeviceDefinitions[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES]; - XnUInt32 nDevicesCount = XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES; - nRetVal = XnDeviceManagerGetDeviceList(aDeviceDefinitions, &nDevicesCount); - XN_IS_STATUS_OK(nRetVal); - - XnUInt32 nDeviceCount = 0; - XnConnectionString* pDeviceConnectionStrings = NULL; - XnUInt32 nTotalCount = 0; - XnDeviceDescriptor* pDescriptor = NULL; - XnChar csConnectionStringPrefix[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nBytesWritten = 0; - - // now enumerate each device - for (XnUInt32 nDevice = 0; nDevice < nDevicesCount; ++nDevice) - { - pDeviceConnectionStrings = aConnectionStrings + nTotalCount; - nDeviceCount = *pnCount - nTotalCount; - - // enumerate device - nRetVal = XnDeviceProxyEnumerateDeviceByName(aDeviceDefinitions[nDevice].cpName, pDeviceConnectionStrings, &nDeviceCount); - - // create connection string prefix for this device - nRetVal = xnOSStrFormat(csConnectionStringPrefix, XN_DEVICE_MAX_STRING_LENGTH, &nBytesWritten, "%s%s", aDeviceDefinitions[nDevice].cpName, XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR); - XN_IS_STATUS_OK(nRetVal); - - // fix each connection string to include device name - for (XnUInt32 nString = 0; nString < nDeviceCount; ++nString) - { - XN_VALIDATE_STR_PREFIX(csConnectionStringPrefix, pDeviceConnectionStrings[nString], XN_DEVICE_MAX_STRING_LENGTH, nRetVal); - } - - // add to total count - nTotalCount += nDeviceCount; - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Create)(XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pDeviceConfig); - XN_VALIDATE_OUTPUT_PTR(pDeviceHandle); - - // get device type from connection string - XN_VALIDATE_INPUT_PTR(pDeviceConfig->cpConnectionString); - - // search for separator - const XnChar* pSeparator = strstr(pDeviceConfig->cpConnectionString, XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR); - if (pSeparator == NULL) - return (XN_STATUS_IO_INVALID_CONNECTION_STRING); - - // copy device name - XnChar csDeviceName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = xnOSStrNCopy(csDeviceName, pDeviceConfig->cpConnectionString, pSeparator - pDeviceConfig->cpConnectionString, XN_DEVICE_MAX_STRING_LENGTH); - XN_IS_STATUS_OK(nRetVal); - csDeviceName[pSeparator - pDeviceConfig->cpConnectionString] = '\0'; - - // create internal device config - XnDeviceConfig InternalConfig = *pDeviceConfig; - - // replace internal connection string - XnConnectionString csInternalConnectionString; - nRetVal = xnOSStrCopy(csInternalConnectionString, pSeparator + 1, XN_DEVICE_MAX_STRING_LENGTH); - XN_IS_STATUS_OK(nRetVal); - - InternalConfig.cpConnectionString = csInternalConnectionString; - - // create the device - nRetVal = XnDeviceProxyCreateDeviceByName(csDeviceName, pDeviceHandle, &InternalConfig); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Destroy)(XnDeviceHandle* pDeviceHandle) -{ - XN_VALIDATE_INPUT_PTR(pDeviceHandle); - XN_VALIDATE_INPUT_PTR(*pDeviceHandle); - - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)*pDeviceHandle; - - // first destroy actual device - XnStatus nRetVal = pHandle->pDesc->Interface.Destroy(&pHandle->ActualDevice); - XN_IS_STATUS_OK(nRetVal); - - // now destroy our handle - XN_FREE_AND_NULL(*pDeviceHandle); - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetSupportedStreams)(const XnDeviceHandle DeviceHandle, const XnChar** aStreamsName, XnUInt32* pnStreamNamesCount) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetSupportedStreams(pHandle->ActualDevice, aStreamsName, pnStreamNamesCount); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CreateStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamType, const XnChar* StreamName, const XnPropertySet* pInitialValues) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.CreateStream(pHandle->ActualDevice, StreamType, StreamName, pInitialValues); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DestroyStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.DestroyStream(pHandle->ActualDevice, StreamName); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(OpenStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.OpenStream(pHandle->ActualDevice, StreamName); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CloseStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.CloseStream(pHandle->ActualDevice, StreamName); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(OpenAllStreams)(const XnDeviceHandle DeviceHandle) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.OpenAllStreams(pHandle->ActualDevice); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CloseAllStreams)(const XnDeviceHandle DeviceHandle) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.CloseAllStreams(pHandle->ActualDevice); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetStreamNames)(const XnDeviceHandle DeviceHandle, const XnChar** pstrNames, XnUInt32* pnNamesCount) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetStreamNames(pHandle->ActualDevice, pstrNames, pnNamesCount); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DoesModuleExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, XnBool* pbDoesExist) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.DoesModuleExist(pHandle->ActualDevice, ModuleName, pbDoesExist); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToStreamsChange)(const XnDeviceHandle DeviceHandle, XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.RegisterToStreamsChange(pHandle->ActualDevice, Handler, pCookie, phCallback); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromStreamsChange)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.UnregisterFromStreamsChange(pHandle->ActualDevice, hCallback); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CreateStreamData)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamData** ppStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(DeviceHandle); - - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - nRetVal = pHandle->pDesc->Interface.CreateStreamData(pHandle->ActualDevice, StreamName, ppStreamData); - XN_IS_STATUS_OK(nRetVal); - - // register this object in the hash - nRetVal = g_StreamOutputHash.Set(*ppStreamData, pHandle->pDesc); - if (nRetVal != XN_STATUS_OK) - { - pHandle->pDesc->Interface.DestroyStreamData(ppStreamData); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DestroyStreamData)(XnStreamData** ppStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(ppStreamData); - - // keep original pointer (before we destroy it) - XnStreamData* pObject = *ppStreamData; - - // find descriptor of the device that created this object - XnDeviceDescriptor* pDesc = NULL; - nRetVal = g_StreamOutputHash.Get(*ppStreamData, (XnValue&)pDesc); - XN_IS_STATUS_OK(nRetVal); - - // destroy the object - nRetVal = pDesc->Interface.DestroyStreamData(ppStreamData); - XN_IS_STATUS_OK(nRetVal); - - // and remove it from map - g_StreamOutputHash.Remove(pObject, (XnValue&)pDesc); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToNewStreamData)(const XnDeviceHandle DeviceHandle, XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.RegisterToNewStreamData(pHandle->ActualDevice, Handler, pCookie, phCallback); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromNewStreamData)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.UnregisterFromNewStreamData(pHandle->ActualDevice, hCallback); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(IsNewDataAvailable)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.IsNewDataAvailable(pHandle->ActualDevice, StreamName, pbNewDataAvailable, pnTimestamp); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(ReadStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.ReadStream(pHandle->ActualDevice, pStreamOutput); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Read)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.Read(pHandle->ActualDevice, pStreamOutputSet); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(WriteStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.WriteStream(pHandle->ActualDevice, pStreamOutput); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Write)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.Write(pHandle->ActualDevice, pStreamOutputSet); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Tell)(const XnDeviceHandle DeviceHandle, XnUInt64* pnTimestamp) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.Tell(pHandle->ActualDevice, pnTimestamp); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Seek)(const XnDeviceHandle DeviceHandle, XnUInt64 nTimestamp) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.Seek(pHandle->ActualDevice, nTimestamp); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(TellFrame)(const XnDeviceHandle DeviceHandle, XnUInt32* pnFrameID) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.TellFrame(pHandle->ActualDevice, pnFrameID); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SeekFrame)(const XnDeviceHandle DeviceHandle, XnUInt32 nFrameID) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.SeekFrame(pHandle->ActualDevice, nFrameID); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DoesPropertyExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.DoesPropertyExist(pHandle->ActualDevice, ModuleName, PropertyName, pbDoesExist); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetPropertyType)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetPropertyType(pHandle->ActualDevice, ModuleName, PropertyName, pnType); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.SetIntProperty(pHandle->ActualDevice, ModuleName, PropertyName, nValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.SetRealProperty(pHandle->ActualDevice, ModuleName, PropertyName, dValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.SetStringProperty(pHandle->ActualDevice, ModuleName, PropertyName, csValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.SetGeneralProperty(pHandle->ActualDevice, ModuleName, PropertyName, Value); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetIntProperty(pHandle->ActualDevice, ModuleName, PropertyName, pnValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetRealProperty(pHandle->ActualDevice, ModuleName, PropertyName, pdValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetStringProperty(pHandle->ActualDevice, ModuleName, PropertyName, csValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer* pValue) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetGeneralProperty(pHandle->ActualDevice, ModuleName, PropertyName, pValue); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(LoadConfigFromFile)(const XnDeviceHandle DeviceHandle, const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.LoadConfigFromFile(pHandle->ActualDevice, csINIFilePath, csSectionName); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(BatchConfig)(const XnDeviceHandle DeviceHandle, const XnPropertySet* pChangeSet) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.BatchConfig(pHandle->ActualDevice, pChangeSet); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetAllProperties)(const XnDeviceHandle DeviceHandle, XnPropertySet* pPropertySet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.GetAllProperties(pHandle->ActualDevice, pPropertySet, bNoStreams, strModule); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.RegisterToPropertyChange(pHandle->ActualDevice, Module, PropertyName, Handler, pCookie, phCallback); -} - -XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) -{ - XN_VALIDATE_INPUT_PTR(DeviceHandle); - XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; - return pHandle->pDesc->Interface.UnregisterFromPropertyChange(pHandle->ActualDevice, Module, PropertyName, hCallback); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnDeviceManager.h" +#include +#include +#include "XnDeviceInterfaceAdapter.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEVICE_PROXY_NAME "Proxy" +#define XN_DEVICE_PROXY_DESCRIPTION "Xiron Proxy Device" +#define XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR ";" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnDeviceProxyDeviceHandle +{ + XnDeviceDescriptor* pDesc; + XnDeviceHandle ActualDevice; +} XnDeviceProxyDeviceHandle; + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +/** Stores a hash of streamoutput objects to their creating device name. */ +XnHash g_StreamOutputHash; + +//--------------------------------------------------------------------------- +// XnDeviceProxy functions +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnDeviceProxyGetDeviceList(XnDeviceDefinition* aDeviceDefinitions, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // take definitions + return XnDeviceManagerGetDeviceList(aDeviceDefinitions, pnCount); +} + +XN_DDK_API XnStatus XnDeviceProxyEnumerateDeviceByName(const XnChar* csDeviceName, XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get device interface + XnDeviceDescriptor* pDescriptor = NULL; + nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); + XN_IS_STATUS_OK(nRetVal); + + // enumerate + nRetVal = pDescriptor->Interface.Enumerate(aConnectionStrings, pnCount); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDeviceProxyCreateDeviceByName(const XnChar* csDeviceName, XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get device interface + XnDeviceDescriptor* pDescriptor = NULL; + nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); + XN_IS_STATUS_OK(nRetVal); + + // now create the actual device + XnDeviceHandle ActualDevice; + nRetVal = pDescriptor->Interface.Create(&ActualDevice, pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + // create our handle + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)xnOSMalloc(sizeof(XnDeviceProxyDeviceHandle)); + if (pHandle == NULL) + { + pDescriptor->Interface.Destroy(&ActualDevice); + return XN_STATUS_ALLOC_FAILED; + } + + pHandle->ActualDevice = ActualDevice; + pHandle->pDesc = pDescriptor; + + // and give it to user + *pDeviceHandle = pHandle; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDeviceProxyCreateDeviceByINIFile(const XnChar* strIniFileName, const XnChar* strSectionName, XnDeviceHandle* pDeviceHandle, const XnPropertySet* pInitialValues /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar cpDeviceName[XN_INI_MAX_LEN]; + XnChar cpMode[XN_INI_MAX_LEN]; + XnChar cpConnectionString[XN_INI_MAX_LEN]; + XnChar cpSharing[XN_INI_MAX_LEN]; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(strIniFileName); + XN_VALIDATE_INPUT_PTR(strSectionName); + XN_VALIDATE_OUTPUT_PTR(pDeviceHandle); + + XnDeviceConfig config; + config.cpConnectionString = cpConnectionString; + config.SharingMode = XN_DEVICE_EXCLUSIVE; + + // Read the device name, mode and connection string from the INI file into a temp strings + XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "Name", cpDeviceName, XN_INI_MAX_LEN, nRetVal); + XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "Mode", cpMode, XN_INI_MAX_LEN, nRetVal); + XN_VALIDATE_READ_INI_STR(strIniFileName, strSectionName, "ConnectionString", cpConnectionString, XN_INI_MAX_LEN, nRetVal); + + // Read optional parameters + if (XN_STATUS_OK == xnOSReadStringFromINI(strIniFileName, strSectionName, "Sharing", cpSharing, XN_INI_MAX_LEN)) + { + if (strcmp(cpSharing, "Exclusive") == 0) + { + config.SharingMode = XN_DEVICE_EXCLUSIVE; + } + else if (strcmp(cpSharing, "Shared") == 0) + { + config.SharingMode = XN_DEVICE_SHARED; + } + else + { + return (XN_STATUS_IO_DEVICE_INVALID_SHARING); + } + } + + if (strcmp(cpMode, "Read") == 0) + { + config.DeviceMode = XN_DEVICE_MODE_READ; + } + else if (strcmp(cpMode, "Write") == 0) + { + config.DeviceMode = XN_DEVICE_MODE_WRITE; + } + else + { + return (XN_STATUS_IO_DEVICE_INVALID_MODE); + } + + config.pInitialValues = pInitialValues; + + nRetVal = XnDeviceProxyCreateDeviceByName(cpDeviceName, pDeviceHandle, &config); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDeviceProxyDestroyStreamOutputByName(const XnChar* csDeviceName, XnStreamData** ppStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(csDeviceName); + XN_VALIDATE_INPUT_PTR(ppStreamOutput); + + // get device interface + XnDeviceDescriptor* pDescriptor = NULL; + nRetVal = XnDeviceManagerGetDeviceByName(csDeviceName, &pDescriptor); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pDescriptor->Interface.DestroyStreamData(ppStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnDeviceProxyGetDeviceName(XnDeviceHandle DeviceHandle, XnChar* csDeviceName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(DeviceHandle); + + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + nRetVal = xnOSStrCopy(csDeviceName, pHandle->pDesc->Definition.cpName, XN_DEVICE_MAX_STRING_LENGTH); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +//--------------------------------------------------------------------------- +// Device Interface implementation +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetDefinition)(XnDeviceDefinition* pDeviceDefinition) +{ + XN_VALIDATE_INPUT_PTR(pDeviceDefinition); + + pDeviceDefinition->cpName = XN_DEVICE_PROXY_NAME; + pDeviceDefinition->cpDescription = XN_DEVICE_PROXY_DESCRIPTION; + pDeviceDefinition->nMajorVersion = XN_PS_MAJOR_VERSION; + pDeviceDefinition->nMinorVersion = XN_PS_MINOR_VERSION; + pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Enumerate)(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(aConnectionStrings); + XN_VALIDATE_INPUT_PTR(pnCount); + + // take all loaded devices + XnDeviceDefinition aDeviceDefinitions[XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES]; + XnUInt32 nDevicesCount = XN_DEVICE_MANAGER_MAX_NUMBER_OF_DEVICES; + nRetVal = XnDeviceManagerGetDeviceList(aDeviceDefinitions, &nDevicesCount); + XN_IS_STATUS_OK(nRetVal); + + XnUInt32 nDeviceCount = 0; + XnConnectionString* pDeviceConnectionStrings = NULL; + XnUInt32 nTotalCount = 0; + XnDeviceDescriptor* pDescriptor = NULL; + XnChar csConnectionStringPrefix[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nBytesWritten = 0; + + // now enumerate each device + for (XnUInt32 nDevice = 0; nDevice < nDevicesCount; ++nDevice) + { + pDeviceConnectionStrings = aConnectionStrings + nTotalCount; + nDeviceCount = *pnCount - nTotalCount; + + // enumerate device + nRetVal = XnDeviceProxyEnumerateDeviceByName(aDeviceDefinitions[nDevice].cpName, pDeviceConnectionStrings, &nDeviceCount); + + // create connection string prefix for this device + nRetVal = xnOSStrFormat(csConnectionStringPrefix, XN_DEVICE_MAX_STRING_LENGTH, &nBytesWritten, "%s%s", aDeviceDefinitions[nDevice].cpName, XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR); + XN_IS_STATUS_OK(nRetVal); + + // fix each connection string to include device name + for (XnUInt32 nString = 0; nString < nDeviceCount; ++nString) + { + XN_VALIDATE_STR_PREFIX(csConnectionStringPrefix, pDeviceConnectionStrings[nString], XN_DEVICE_MAX_STRING_LENGTH, nRetVal); + } + + // add to total count + nTotalCount += nDeviceCount; + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Create)(XnDeviceHandle* pDeviceHandle, const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pDeviceConfig); + XN_VALIDATE_OUTPUT_PTR(pDeviceHandle); + + // get device type from connection string + XN_VALIDATE_INPUT_PTR(pDeviceConfig->cpConnectionString); + + // search for separator + const XnChar* pSeparator = strstr(pDeviceConfig->cpConnectionString, XN_DEVICE_PROXY_CONNECTION_STRING_SEPARATOR); + if (pSeparator == NULL) + return (XN_STATUS_IO_INVALID_CONNECTION_STRING); + + // copy device name + XnChar csDeviceName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = xnOSStrNCopy(csDeviceName, pDeviceConfig->cpConnectionString, pSeparator - pDeviceConfig->cpConnectionString, XN_DEVICE_MAX_STRING_LENGTH); + XN_IS_STATUS_OK(nRetVal); + csDeviceName[pSeparator - pDeviceConfig->cpConnectionString] = '\0'; + + // create internal device config + XnDeviceConfig InternalConfig = *pDeviceConfig; + + // replace internal connection string + XnConnectionString csInternalConnectionString; + nRetVal = xnOSStrCopy(csInternalConnectionString, pSeparator + 1, XN_DEVICE_MAX_STRING_LENGTH); + XN_IS_STATUS_OK(nRetVal); + + InternalConfig.cpConnectionString = csInternalConnectionString; + + // create the device + nRetVal = XnDeviceProxyCreateDeviceByName(csDeviceName, pDeviceHandle, &InternalConfig); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Destroy)(XnDeviceHandle* pDeviceHandle) +{ + XN_VALIDATE_INPUT_PTR(pDeviceHandle); + XN_VALIDATE_INPUT_PTR(*pDeviceHandle); + + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)*pDeviceHandle; + + // first destroy actual device + XnStatus nRetVal = pHandle->pDesc->Interface.Destroy(&pHandle->ActualDevice); + XN_IS_STATUS_OK(nRetVal); + + // now destroy our handle + XN_FREE_AND_NULL(*pDeviceHandle); + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetSupportedStreams)(const XnDeviceHandle DeviceHandle, const XnChar** aStreamsName, XnUInt32* pnStreamNamesCount) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetSupportedStreams(pHandle->ActualDevice, aStreamsName, pnStreamNamesCount); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CreateStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamType, const XnChar* StreamName, const XnPropertySet* pInitialValues) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.CreateStream(pHandle->ActualDevice, StreamType, StreamName, pInitialValues); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DestroyStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.DestroyStream(pHandle->ActualDevice, StreamName); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(OpenStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.OpenStream(pHandle->ActualDevice, StreamName); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CloseStream)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.CloseStream(pHandle->ActualDevice, StreamName); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(OpenAllStreams)(const XnDeviceHandle DeviceHandle) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.OpenAllStreams(pHandle->ActualDevice); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CloseAllStreams)(const XnDeviceHandle DeviceHandle) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.CloseAllStreams(pHandle->ActualDevice); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetStreamNames)(const XnDeviceHandle DeviceHandle, const XnChar** pstrNames, XnUInt32* pnNamesCount) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetStreamNames(pHandle->ActualDevice, pstrNames, pnNamesCount); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DoesModuleExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, XnBool* pbDoesExist) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.DoesModuleExist(pHandle->ActualDevice, ModuleName, pbDoesExist); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToStreamsChange)(const XnDeviceHandle DeviceHandle, XnDeviceOnStreamsChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.RegisterToStreamsChange(pHandle->ActualDevice, Handler, pCookie, phCallback); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromStreamsChange)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.UnregisterFromStreamsChange(pHandle->ActualDevice, hCallback); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(CreateStreamData)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamData** ppStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(DeviceHandle); + + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + nRetVal = pHandle->pDesc->Interface.CreateStreamData(pHandle->ActualDevice, StreamName, ppStreamData); + XN_IS_STATUS_OK(nRetVal); + + // register this object in the hash + nRetVal = g_StreamOutputHash.Set(*ppStreamData, pHandle->pDesc); + if (nRetVal != XN_STATUS_OK) + { + pHandle->pDesc->Interface.DestroyStreamData(ppStreamData); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DestroyStreamData)(XnStreamData** ppStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(ppStreamData); + + // keep original pointer (before we destroy it) + XnStreamData* pObject = *ppStreamData; + + // find descriptor of the device that created this object + XnDeviceDescriptor* pDesc = NULL; + nRetVal = g_StreamOutputHash.Get(*ppStreamData, (XnValue&)pDesc); + XN_IS_STATUS_OK(nRetVal); + + // destroy the object + nRetVal = pDesc->Interface.DestroyStreamData(ppStreamData); + XN_IS_STATUS_OK(nRetVal); + + // and remove it from map + g_StreamOutputHash.Remove(pObject, (XnValue&)pDesc); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToNewStreamData)(const XnDeviceHandle DeviceHandle, XnDeviceOnNewStreamDataEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.RegisterToNewStreamData(pHandle->ActualDevice, Handler, pCookie, phCallback); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromNewStreamData)(const XnDeviceHandle DeviceHandle, XnCallbackHandle hCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.UnregisterFromNewStreamData(pHandle->ActualDevice, hCallback); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(IsNewDataAvailable)(const XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnBool* pbNewDataAvailable, XnUInt64* pnTimestamp) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.IsNewDataAvailable(pHandle->ActualDevice, StreamName, pbNewDataAvailable, pnTimestamp); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(ReadStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.ReadStream(pHandle->ActualDevice, pStreamOutput); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Read)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.Read(pHandle->ActualDevice, pStreamOutputSet); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(WriteStream)(const XnDeviceHandle DeviceHandle, XnStreamData* pStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.WriteStream(pHandle->ActualDevice, pStreamOutput); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Write)(const XnDeviceHandle DeviceHandle, XnStreamDataSet* pStreamOutputSet) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.Write(pHandle->ActualDevice, pStreamOutputSet); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Tell)(const XnDeviceHandle DeviceHandle, XnUInt64* pnTimestamp) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.Tell(pHandle->ActualDevice, pnTimestamp); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(Seek)(const XnDeviceHandle DeviceHandle, XnUInt64 nTimestamp) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.Seek(pHandle->ActualDevice, nTimestamp); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(TellFrame)(const XnDeviceHandle DeviceHandle, XnUInt32* pnFrameID) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.TellFrame(pHandle->ActualDevice, pnFrameID); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SeekFrame)(const XnDeviceHandle DeviceHandle, XnUInt32 nFrameID) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.SeekFrame(pHandle->ActualDevice, nFrameID); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(DoesPropertyExist)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnBool* pbDoesExist) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.DoesPropertyExist(pHandle->ActualDevice, ModuleName, PropertyName, pbDoesExist); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetPropertyType)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnPropertyType* pnType) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetPropertyType(pHandle->ActualDevice, ModuleName, PropertyName, pnType); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.SetIntProperty(pHandle->ActualDevice, ModuleName, PropertyName, nValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.SetRealProperty(pHandle->ActualDevice, ModuleName, PropertyName, dValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.SetStringProperty(pHandle->ActualDevice, ModuleName, PropertyName, csValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(SetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnGeneralBuffer Value) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.SetGeneralProperty(pHandle->ActualDevice, ModuleName, PropertyName, Value); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetIntProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetIntProperty(pHandle->ActualDevice, ModuleName, PropertyName, pnValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetRealProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetRealProperty(pHandle->ActualDevice, ModuleName, PropertyName, pdValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetStringProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, XnChar* csValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetStringProperty(pHandle->ActualDevice, ModuleName, PropertyName, csValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetGeneralProperty)(const XnDeviceHandle DeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer* pValue) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetGeneralProperty(pHandle->ActualDevice, ModuleName, PropertyName, pValue); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(LoadConfigFromFile)(const XnDeviceHandle DeviceHandle, const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.LoadConfigFromFile(pHandle->ActualDevice, csINIFilePath, csSectionName); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(BatchConfig)(const XnDeviceHandle DeviceHandle, const XnPropertySet* pChangeSet) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.BatchConfig(pHandle->ActualDevice, pChangeSet); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(GetAllProperties)(const XnDeviceHandle DeviceHandle, XnPropertySet* pPropertySet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.GetAllProperties(pHandle->ActualDevice, pPropertySet, bNoStreams, strModule); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(RegisterToPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnDeviceOnPropertyChangedEventHandler Handler, void* pCookie, XnCallbackHandle* phCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.RegisterToPropertyChange(pHandle->ActualDevice, Module, PropertyName, Handler, pCookie, phCallback); +} + +XN_DDK_API XnStatus XN_DEVICE_PROXY_PROTO(UnregisterFromPropertyChange)(const XnDeviceHandle DeviceHandle, const XnChar* Module, const XnChar* PropertyName, XnCallbackHandle hCallback) +{ + XN_VALIDATE_INPUT_PTR(DeviceHandle); + XnDeviceProxyDeviceHandle* pHandle = (XnDeviceProxyDeviceHandle*)DeviceHandle; + return pHandle->pDesc->Interface.UnregisterFromPropertyChange(pHandle->ActualDevice, Module, PropertyName, hCallback); +} + diff --git a/Source/XnDDK/XnDeviceStream.cpp b/Source/XnDDK/XnDeviceStream.cpp index 4aab57a..78e7f16 100644 --- a/Source/XnDDK/XnDeviceStream.cpp +++ b/Source/XnDDK/XnDeviceStream.cpp @@ -1,276 +1,276 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceStream.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDeviceStream::XnDeviceStream(const XnChar* csType, const XnChar* csName) : - XnDeviceModule(csName), - m_IsStream(XN_STREAM_PROPERTY_IS_STREAM, TRUE), - m_Type(XN_STREAM_PROPERTY_TYPE, csType), - m_IsOpen(XN_STREAM_PROPERTY_STATE, FALSE), - m_RequiredSize(XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE), - m_OutputFormat(XN_STREAM_PROPERTY_OUTPUT_FORMAT), - m_IsMirrored(XN_MODULE_PROPERTY_MIRROR), - m_bNewDataAvailable(FALSE), - m_nTimestamp(0), - m_nFrameID(0), - m_pNewDataCallback(NULL) -{ -} - -XnStatus XnDeviceStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init module - nRetVal = XnDeviceModule::Init(); - XN_IS_STATUS_OK(nRetVal); - - // cs - nRetVal = xnOSCreateCriticalSection(&m_hCriticalSection); - XN_IS_STATUS_OK(nRetVal); - - m_IsOpen.UpdateSetCallback(SetIsOpenCallback, this); - m_OutputFormat.UpdateSetCallback(SetOutputFormatCallback, this); - m_IsMirrored.UpdateSetCallback(SetIsMirrorCallback, this); - - XN_VALIDATE_ADD_PROPERTIES(this, &m_IsStream, &m_Type, &m_IsOpen, &m_OutputFormat, &m_RequiredSize, &m_IsMirrored); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::Free() -{ - xnOSCloseCriticalSection(&m_hCriticalSection); - XnDeviceModule::Free(); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::Open() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_IsOpen.UnsafeUpdateValue(TRUE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::Close() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_IsOpen.UnsafeUpdateValue(FALSE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::SetOutputFormat(XnOutputFormats nOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_OutputFormat.UnsafeUpdateValue(nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::SetMirror(XnBool bIsMirrored) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_IsMirrored.UnsafeUpdateValue(bIsMirrored); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnDeviceStream::NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID) -{ - m_bNewDataAvailable = TRUE; - m_nTimestamp = nTimestamp; - m_nFrameID = nFrameID; - - if (m_pNewDataCallback != NULL) - { - m_pNewDataCallback(this, nTimestamp, nFrameID, m_pNewDataCallbackCookie); - } -} - -void XnDeviceStream::ResetLastTimestampAndFrameID() -{ - m_nFrameID = 0; - m_nTimestamp = 0; -} - -void XnDeviceStream::SetNewDataCallback(NewDataCallbackPtr pFunc, void* pCookie) -{ - m_pNewDataCallback = pFunc; - m_pNewDataCallbackCookie = pCookie; -} - -XnStatus XnDeviceStream::CreateStreamData(XnStreamData** ppStreamData) -{ - return XnStreamDataCreate(ppStreamData, GetName(), GetRequiredDataSize()); -} - -XnStatus XnDeviceStream::Read(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check the size of the stream output object - nRetVal = XnStreamDataCheckSize(pStreamOutput, GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - // first mark old data as old - pStreamOutput->bIsNew = FALSE; - - // now check if we have some new data - if (m_bNewDataAvailable) - { - // copy data - nRetVal = ReadImpl(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - xnOSEnterCriticalSection(&m_hCriticalSection); - XnBool bMirror = IsMirrored(); - xnOSLeaveCriticalSection(&m_hCriticalSection); - - // mirror it if needed - if (bMirror) - { - nRetVal = Mirror(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - } - - // mark that data is new - pStreamOutput->bIsNew = TRUE; - - // and that we don't have new info - m_bNewDataAvailable = FALSE; - } - else - { - nRetVal = HandleNoNewData(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::HandleNoNewData(XnStreamData* pStreamOutput) -{ - return XN_STATUS_OK; -} - -XnStatus XnDeviceStream::Write(XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // make sure data is new - if (pStreamData->bIsNew) - { - nRetVal = WriteImpl(pStreamData); - XN_IS_STATUS_OK(nRetVal); - - NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::RegisterRequiredSizeProperty(XnProperty* pProperty) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // make sure the property belongs to this module (because we never unregister from it) - XN_ASSERT(strcmp(pProperty->GetModule(), GetName()) == 0); - - XnCallbackHandle hCallbackDummy; - nRetVal = pProperty->OnChangeEvent().Register(UpdateRequiredSizeCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - // recalculate it - nRetVal = UpdateRequiredSize(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceStream::UpdateRequiredSize() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nRequiredSize; - nRetVal = CalcRequiredSize(&nRequiredSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_RequiredSize.UnsafeUpdateValue(nRequiredSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceStream::UpdateRequiredSizeCallback(const XnProperty* pSenser, void* pCookie) -{ - XnDeviceStream* pStream = (XnDeviceStream*)pCookie; - return pStream->UpdateRequiredSize(); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetIsOpenCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceStream* pStream = (XnDeviceStream*)pCookie; - if (nValue == TRUE) - { - return pStream->Open(); - } - else - { - return pStream->Close(); - } -} - -XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetOutputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceStream* pStream = (XnDeviceStream*)pCookie; - return pStream->SetOutputFormat((XnOutputFormats)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetIsMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnDeviceStream* pStream = (XnDeviceStream*)pCookie; - return pStream->SetMirror((XnBool)nValue); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceStream.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDeviceStream::XnDeviceStream(const XnChar* csType, const XnChar* csName) : + XnDeviceModule(csName), + m_IsStream(XN_STREAM_PROPERTY_IS_STREAM, TRUE), + m_Type(XN_STREAM_PROPERTY_TYPE, csType), + m_IsOpen(XN_STREAM_PROPERTY_STATE, FALSE), + m_RequiredSize(XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE), + m_OutputFormat(XN_STREAM_PROPERTY_OUTPUT_FORMAT), + m_IsMirrored(XN_MODULE_PROPERTY_MIRROR), + m_bNewDataAvailable(FALSE), + m_nTimestamp(0), + m_nFrameID(0), + m_pNewDataCallback(NULL) +{ +} + +XnStatus XnDeviceStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init module + nRetVal = XnDeviceModule::Init(); + XN_IS_STATUS_OK(nRetVal); + + // cs + nRetVal = xnOSCreateCriticalSection(&m_hCriticalSection); + XN_IS_STATUS_OK(nRetVal); + + m_IsOpen.UpdateSetCallback(SetIsOpenCallback, this); + m_OutputFormat.UpdateSetCallback(SetOutputFormatCallback, this); + m_IsMirrored.UpdateSetCallback(SetIsMirrorCallback, this); + + XN_VALIDATE_ADD_PROPERTIES(this, &m_IsStream, &m_Type, &m_IsOpen, &m_OutputFormat, &m_RequiredSize, &m_IsMirrored); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::Free() +{ + xnOSCloseCriticalSection(&m_hCriticalSection); + XnDeviceModule::Free(); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::Open() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_IsOpen.UnsafeUpdateValue(TRUE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::Close() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_IsOpen.UnsafeUpdateValue(FALSE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::SetOutputFormat(XnOutputFormats nOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_OutputFormat.UnsafeUpdateValue(nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::SetMirror(XnBool bIsMirrored) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_IsMirrored.UnsafeUpdateValue(bIsMirrored); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnDeviceStream::NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID) +{ + m_bNewDataAvailable = TRUE; + m_nTimestamp = nTimestamp; + m_nFrameID = nFrameID; + + if (m_pNewDataCallback != NULL) + { + m_pNewDataCallback(this, nTimestamp, nFrameID, m_pNewDataCallbackCookie); + } +} + +void XnDeviceStream::ResetLastTimestampAndFrameID() +{ + m_nFrameID = 0; + m_nTimestamp = 0; +} + +void XnDeviceStream::SetNewDataCallback(NewDataCallbackPtr pFunc, void* pCookie) +{ + m_pNewDataCallback = pFunc; + m_pNewDataCallbackCookie = pCookie; +} + +XnStatus XnDeviceStream::CreateStreamData(XnStreamData** ppStreamData) +{ + return XnStreamDataCreate(ppStreamData, GetName(), GetRequiredDataSize()); +} + +XnStatus XnDeviceStream::Read(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check the size of the stream output object + nRetVal = XnStreamDataCheckSize(pStreamOutput, GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + // first mark old data as old + pStreamOutput->bIsNew = FALSE; + + // now check if we have some new data + if (m_bNewDataAvailable) + { + // copy data + nRetVal = ReadImpl(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + xnOSEnterCriticalSection(&m_hCriticalSection); + XnBool bMirror = IsMirrored(); + xnOSLeaveCriticalSection(&m_hCriticalSection); + + // mirror it if needed + if (bMirror) + { + nRetVal = Mirror(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + } + + // mark that data is new + pStreamOutput->bIsNew = TRUE; + + // and that we don't have new info + m_bNewDataAvailable = FALSE; + } + else + { + nRetVal = HandleNoNewData(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::HandleNoNewData(XnStreamData* pStreamOutput) +{ + return XN_STATUS_OK; +} + +XnStatus XnDeviceStream::Write(XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // make sure data is new + if (pStreamData->bIsNew) + { + nRetVal = WriteImpl(pStreamData); + XN_IS_STATUS_OK(nRetVal); + + NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::RegisterRequiredSizeProperty(XnProperty* pProperty) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // make sure the property belongs to this module (because we never unregister from it) + XN_ASSERT(strcmp(pProperty->GetModule(), GetName()) == 0); + + XnCallbackHandle hCallbackDummy; + nRetVal = pProperty->OnChangeEvent().Register(UpdateRequiredSizeCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + // recalculate it + nRetVal = UpdateRequiredSize(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceStream::UpdateRequiredSize() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nRequiredSize; + nRetVal = CalcRequiredSize(&nRequiredSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_RequiredSize.UnsafeUpdateValue(nRequiredSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceStream::UpdateRequiredSizeCallback(const XnProperty* pSenser, void* pCookie) +{ + XnDeviceStream* pStream = (XnDeviceStream*)pCookie; + return pStream->UpdateRequiredSize(); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetIsOpenCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceStream* pStream = (XnDeviceStream*)pCookie; + if (nValue == TRUE) + { + return pStream->Open(); + } + else + { + return pStream->Close(); + } +} + +XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetOutputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceStream* pStream = (XnDeviceStream*)pCookie; + return pStream->SetOutputFormat((XnOutputFormats)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnDeviceStream::SetIsMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnDeviceStream* pStream = (XnDeviceStream*)pCookie; + return pStream->SetMirror((XnBool)nValue); +} diff --git a/Source/XnDDK/XnDeviceStream.h b/Source/XnDDK/XnDeviceStream.h index 6eefd38..fdc2edc 100644 --- a/Source/XnDDK/XnDeviceStream.h +++ b/Source/XnDDK/XnDeviceStream.h @@ -1,157 +1,157 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_STREAM_H__ -#define __XN_DEVICE_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a stream in a device. */ -class XN_DDK_CPP_API XnDeviceStream : public XnDeviceModule -{ -public: - XnDeviceStream(const XnChar* csType, const XnChar* csName); - ~XnDeviceStream() { Free(); } - - XnStatus Init(); - XnStatus Free(); - - virtual XnStatus CreateStreamData(XnStreamData** ppStreamData); - - /** Reads latest stream info into stream output. */ - virtual XnStatus Read(XnStreamData* pStreamData); - - /** Writes stream data into stream. */ - virtual XnStatus Write(XnStreamData* pStreamData); - - /** Checks if new data is available from stream. */ - inline XnBool IsNewDataAvailable() const { return m_bNewDataAvailable; } - - typedef void (*NewDataCallbackPtr)(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie); - - /** Sets a function callback to be called when new data is available. */ - void SetNewDataCallback(NewDataCallbackPtr pFunc, void* pCookie); - - /** Notifies new data is available in this stream. */ - void NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID); - - void ResetLastTimestampAndFrameID(); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline const XnChar* GetType() const { return m_Type.GetValue(); } - inline XnBool IsOpen() const { return (XnBool)m_IsOpen.GetValue(); } - inline XnOutputFormats GetOutputFormat() const { return (XnOutputFormats)m_OutputFormat.GetValue(); } - inline XnBool IsMirrored() const { return (XnBool)m_IsMirrored.GetValue(); } - inline XnUInt32 GetRequiredDataSize() const { return (XnUInt32)m_RequiredSize.GetValue(); } - inline XnUInt64 GetLastTimestamp() const { return m_nTimestamp; } - inline XnUInt32 GetLastFrameID() const { return m_nFrameID; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus Open(); - virtual XnStatus Close(); - virtual XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); - virtual XnStatus SetMirror(XnBool bIsMirrored); - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& IsOpenProperty() { return m_IsOpen; } - inline XnActualIntProperty& OutputFormatProperty() { return m_OutputFormat; } - inline XnActualIntProperty& RequiredSizeProperty() { return m_RequiredSize; } - inline XnActualIntProperty& IsMirroredProperty() { return m_IsMirrored; } - - inline XN_CRITICAL_SECTION_HANDLE* GetLock() { return &m_hCriticalSection; } - -protected: - //--------------------------------------------------------------------------- - // Virtual Functions - //--------------------------------------------------------------------------- - - /** Actually reads data into the stream output object. */ - virtual XnStatus ReadImpl(XnStreamData* pStreamOutput) = 0; - /** Actually writes data from the stream output object. */ - virtual XnStatus WriteImpl(XnStreamData* pStreamData) = 0; - /** Performs mirror on the given stream output. */ - virtual XnStatus Mirror(XnStreamData* pStreamOutput) const = 0; - /** Calculates the required size. */ - virtual XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const = 0; - /** Allows inheriting classes to do something when user called Read(), and there is no new data. */ - virtual XnStatus HandleNoNewData(XnStreamData* pStreamOutput); - - //--------------------------------------------------------------------------- - // Utility Functions - //--------------------------------------------------------------------------- - XnStatus RegisterRequiredSizeProperty(XnProperty* pProperty); - -private: - XnStatus UpdateRequiredSize(); - - static XnStatus XN_CALLBACK_TYPE UpdateRequiredSizeCallback(const XnProperty* pSenser, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetIsOpenCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetOutputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetIsMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_IsStream; - XnActualStringProperty m_Type; - XnActualIntProperty m_IsOpen; - XnActualIntProperty m_RequiredSize; - XnActualIntProperty m_OutputFormat; - XnActualIntProperty m_IsMirrored; - - /** TRUE if new data is available. */ - XnBool m_bNewDataAvailable; - /** Current timestamp of this stream. */ - XnUInt64 m_nTimestamp; - /** Current frame id of this stream. */ - XnUInt32 m_nFrameID; - - NewDataCallbackPtr m_pNewDataCallback; - void* m_pNewDataCallbackCookie; - - XN_CRITICAL_SECTION_HANDLE m_hCriticalSection; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_STREAM_H__ +#define __XN_DEVICE_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a stream in a device. */ +class XN_DDK_CPP_API XnDeviceStream : public XnDeviceModule +{ +public: + XnDeviceStream(const XnChar* csType, const XnChar* csName); + ~XnDeviceStream() { Free(); } + + XnStatus Init(); + XnStatus Free(); + + virtual XnStatus CreateStreamData(XnStreamData** ppStreamData); + + /** Reads latest stream info into stream output. */ + virtual XnStatus Read(XnStreamData* pStreamData); + + /** Writes stream data into stream. */ + virtual XnStatus Write(XnStreamData* pStreamData); + + /** Checks if new data is available from stream. */ + inline XnBool IsNewDataAvailable() const { return m_bNewDataAvailable; } + + typedef void (*NewDataCallbackPtr)(XnDeviceStream* pSender, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie); + + /** Sets a function callback to be called when new data is available. */ + void SetNewDataCallback(NewDataCallbackPtr pFunc, void* pCookie); + + /** Notifies new data is available in this stream. */ + void NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID); + + void ResetLastTimestampAndFrameID(); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline const XnChar* GetType() const { return m_Type.GetValue(); } + inline XnBool IsOpen() const { return (XnBool)m_IsOpen.GetValue(); } + inline XnOutputFormats GetOutputFormat() const { return (XnOutputFormats)m_OutputFormat.GetValue(); } + inline XnBool IsMirrored() const { return (XnBool)m_IsMirrored.GetValue(); } + inline XnUInt32 GetRequiredDataSize() const { return (XnUInt32)m_RequiredSize.GetValue(); } + inline XnUInt64 GetLastTimestamp() const { return m_nTimestamp; } + inline XnUInt32 GetLastFrameID() const { return m_nFrameID; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus Open(); + virtual XnStatus Close(); + virtual XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); + virtual XnStatus SetMirror(XnBool bIsMirrored); + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& IsOpenProperty() { return m_IsOpen; } + inline XnActualIntProperty& OutputFormatProperty() { return m_OutputFormat; } + inline XnActualIntProperty& RequiredSizeProperty() { return m_RequiredSize; } + inline XnActualIntProperty& IsMirroredProperty() { return m_IsMirrored; } + + inline XN_CRITICAL_SECTION_HANDLE* GetLock() { return &m_hCriticalSection; } + +protected: + //--------------------------------------------------------------------------- + // Virtual Functions + //--------------------------------------------------------------------------- + + /** Actually reads data into the stream output object. */ + virtual XnStatus ReadImpl(XnStreamData* pStreamOutput) = 0; + /** Actually writes data from the stream output object. */ + virtual XnStatus WriteImpl(XnStreamData* pStreamData) = 0; + /** Performs mirror on the given stream output. */ + virtual XnStatus Mirror(XnStreamData* pStreamOutput) const = 0; + /** Calculates the required size. */ + virtual XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const = 0; + /** Allows inheriting classes to do something when user called Read(), and there is no new data. */ + virtual XnStatus HandleNoNewData(XnStreamData* pStreamOutput); + + //--------------------------------------------------------------------------- + // Utility Functions + //--------------------------------------------------------------------------- + XnStatus RegisterRequiredSizeProperty(XnProperty* pProperty); + +private: + XnStatus UpdateRequiredSize(); + + static XnStatus XN_CALLBACK_TYPE UpdateRequiredSizeCallback(const XnProperty* pSenser, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetIsOpenCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetOutputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetIsMirrorCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_IsStream; + XnActualStringProperty m_Type; + XnActualIntProperty m_IsOpen; + XnActualIntProperty m_RequiredSize; + XnActualIntProperty m_OutputFormat; + XnActualIntProperty m_IsMirrored; + + /** TRUE if new data is available. */ + XnBool m_bNewDataAvailable; + /** Current timestamp of this stream. */ + XnUInt64 m_nTimestamp; + /** Current frame id of this stream. */ + XnUInt32 m_nFrameID; + + NewDataCallbackPtr m_pNewDataCallback; + void* m_pNewDataCallbackCookie; + + XN_CRITICAL_SECTION_HANDLE m_hCriticalSection; +}; + #endif //__XN_DEVICE_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnFrameBufferManager.cpp b/Source/XnDDK/XnFrameBufferManager.cpp index 816fca2..97a4598 100644 --- a/Source/XnDDK/XnFrameBufferManager.cpp +++ b/Source/XnDDK/XnFrameBufferManager.cpp @@ -1,206 +1,206 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameBufferManager.h" -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFrameBufferManager::XnFrameBufferManager(XnBufferPool* pBufferPool) : - m_pBufferPool(pBufferPool), - m_pWorkingBuffer(NULL), - m_pStableBuffer(NULL), - m_nStableFrameID(0), - m_nStableTimestamp(0), - m_hLock(NULL) -{ -} - -XnFrameBufferManager::~XnFrameBufferManager() -{ - Free(); -} - -XnStatus XnFrameBufferManager::Init(XnUInt32 nBufferSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSCreateCriticalSection(&m_hLock); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pBufferPool->Init(nBufferSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = Reallocate(nBufferSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnFrameBufferManager::Free() -{ - if (m_hLock != NULL) - { - xnOSCloseCriticalSection(&m_hLock); - m_hLock = NULL; - } -} - -XnStatus XnFrameBufferManager::Reallocate(XnUInt32 nBufferSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnOSEnterCriticalSection(&m_hLock); - - nRetVal = m_pBufferPool->ChangeBufferSize(nBufferSize); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(&m_hLock); - return (nRetVal); - } - - // release current ones - if (m_pWorkingBuffer != NULL) - { - m_pBufferPool->DecRef(m_pWorkingBuffer); - } - - if (m_pStableBuffer != NULL) - { - m_pBufferPool->DecRef(m_pStableBuffer); - } - - // and take one - if (nBufferSize == 0) - { - m_pWorkingBuffer = NULL; - m_pStableBuffer = NULL; - } - else - { - // take working buffer - nRetVal = m_pBufferPool->GetBuffer(&m_pWorkingBuffer); - XN_IS_STATUS_OK(nRetVal); - } - - xnOSLeaveCriticalSection(&m_hLock); - - return (XN_STATUS_OK); -} - -void XnFrameBufferManager::MarkWriteBufferAsStable(XnUInt64 nTimestamp, XnUInt32* pnFrameID) -{ - xnOSEnterCriticalSection(&m_hLock); - - // lock buffer pool (for rollback option) - m_pBufferPool->Lock(); - - XnBuffer* pPrevStable = m_pStableBuffer; - - // release previous stable - if (m_pStableBuffer != NULL) - { - m_pBufferPool->DecRef(m_pStableBuffer); - } - - // mark working as stable - m_nStableFrameID++; - m_nStableTimestamp = nTimestamp; - *pnFrameID = m_nStableFrameID; - - m_pStableBuffer = m_pWorkingBuffer; // no need to add ref, working buffer will be replaced in a moment - - // take a new working buffer - XnStatus nRetVal = m_pBufferPool->GetBuffer(&m_pWorkingBuffer); - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_DDK, "Failed to get new working buffer!"); - // we'll return back to our old working one - m_pWorkingBuffer->Reset(); - - m_pStableBuffer = pPrevStable; - m_pBufferPool->AddRef(m_pStableBuffer); - m_pBufferPool->Unlock(); - return; - } - - m_pBufferPool->Unlock(); - xnOSLeaveCriticalSection(&m_hLock); - - // reset new working - m_pWorkingBuffer->Reset(); - - // notify stream that new data is available - m_NewFrameEvent.Raise(this, m_nStableTimestamp); -} - -void XnFrameBufferManager::ReadLastStableBuffer(XnBuffer** ppBuffer, XnUInt64* pnTimestamp, XnUInt32* pnFrameID) -{ - xnOSEnterCriticalSection(&m_hLock); - - // take a pointer to stable one - *ppBuffer = m_pStableBuffer; - // and add ref to it (so it wouldn't be deleted) - if (m_pStableBuffer != NULL) - { - m_pBufferPool->AddRef(m_pStableBuffer); - } - - // take props - *pnTimestamp = m_nStableTimestamp; - *pnFrameID = m_nStableFrameID; - - xnOSLeaveCriticalSection(&m_hLock); -} - -XnStatus XnFrameBufferManager::CopyLastStableBuffer(void* pDest, XnUInt32 nDestSize, XnUInt32* pnWritten) -{ - // do this inside a lock (so we won't erase memory during copy) - xnOSEnterCriticalSection(&m_hLock); - - // check size - if (nDestSize < m_pStableBuffer->GetSize()) - { - xnOSLeaveCriticalSection(&m_hLock); - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - // copy - m_pStableBuffer->UnsafeCopy(pDest); - *pnWritten = m_pStableBuffer->GetSize(); - - xnOSLeaveCriticalSection(&m_hLock); - - return XN_STATUS_OK; -} - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameBufferManager.h" +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFrameBufferManager::XnFrameBufferManager(XnBufferPool* pBufferPool) : + m_pBufferPool(pBufferPool), + m_pWorkingBuffer(NULL), + m_pStableBuffer(NULL), + m_nStableFrameID(0), + m_nStableTimestamp(0), + m_hLock(NULL) +{ +} + +XnFrameBufferManager::~XnFrameBufferManager() +{ + Free(); +} + +XnStatus XnFrameBufferManager::Init(XnUInt32 nBufferSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pBufferPool->Init(nBufferSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = Reallocate(nBufferSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnFrameBufferManager::Free() +{ + if (m_hLock != NULL) + { + xnOSCloseCriticalSection(&m_hLock); + m_hLock = NULL; + } +} + +XnStatus XnFrameBufferManager::Reallocate(XnUInt32 nBufferSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnOSEnterCriticalSection(&m_hLock); + + nRetVal = m_pBufferPool->ChangeBufferSize(nBufferSize); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(&m_hLock); + return (nRetVal); + } + + // release current ones + if (m_pWorkingBuffer != NULL) + { + m_pBufferPool->DecRef(m_pWorkingBuffer); + } + + if (m_pStableBuffer != NULL) + { + m_pBufferPool->DecRef(m_pStableBuffer); + } + + // and take one + if (nBufferSize == 0) + { + m_pWorkingBuffer = NULL; + m_pStableBuffer = NULL; + } + else + { + // take working buffer + nRetVal = m_pBufferPool->GetBuffer(&m_pWorkingBuffer); + XN_IS_STATUS_OK(nRetVal); + } + + xnOSLeaveCriticalSection(&m_hLock); + + return (XN_STATUS_OK); +} + +void XnFrameBufferManager::MarkWriteBufferAsStable(XnUInt64 nTimestamp, XnUInt32* pnFrameID) +{ + xnOSEnterCriticalSection(&m_hLock); + + // lock buffer pool (for rollback option) + m_pBufferPool->Lock(); + + XnBuffer* pPrevStable = m_pStableBuffer; + + // release previous stable + if (m_pStableBuffer != NULL) + { + m_pBufferPool->DecRef(m_pStableBuffer); + } + + // mark working as stable + m_nStableFrameID++; + m_nStableTimestamp = nTimestamp; + *pnFrameID = m_nStableFrameID; + + m_pStableBuffer = m_pWorkingBuffer; // no need to add ref, working buffer will be replaced in a moment + + // take a new working buffer + XnStatus nRetVal = m_pBufferPool->GetBuffer(&m_pWorkingBuffer); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_DDK, "Failed to get new working buffer!"); + // we'll return back to our old working one + m_pWorkingBuffer->Reset(); + + m_pStableBuffer = pPrevStable; + m_pBufferPool->AddRef(m_pStableBuffer); + m_pBufferPool->Unlock(); + return; + } + + m_pBufferPool->Unlock(); + xnOSLeaveCriticalSection(&m_hLock); + + // reset new working + m_pWorkingBuffer->Reset(); + + // notify stream that new data is available + m_NewFrameEvent.Raise(this, m_nStableTimestamp); +} + +void XnFrameBufferManager::ReadLastStableBuffer(XnBuffer** ppBuffer, XnUInt64* pnTimestamp, XnUInt32* pnFrameID) +{ + xnOSEnterCriticalSection(&m_hLock); + + // take a pointer to stable one + *ppBuffer = m_pStableBuffer; + // and add ref to it (so it wouldn't be deleted) + if (m_pStableBuffer != NULL) + { + m_pBufferPool->AddRef(m_pStableBuffer); + } + + // take props + *pnTimestamp = m_nStableTimestamp; + *pnFrameID = m_nStableFrameID; + + xnOSLeaveCriticalSection(&m_hLock); +} + +XnStatus XnFrameBufferManager::CopyLastStableBuffer(void* pDest, XnUInt32 nDestSize, XnUInt32* pnWritten) +{ + // do this inside a lock (so we won't erase memory during copy) + xnOSEnterCriticalSection(&m_hLock); + + // check size + if (nDestSize < m_pStableBuffer->GetSize()) + { + xnOSLeaveCriticalSection(&m_hLock); + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + // copy + m_pStableBuffer->UnsafeCopy(pDest); + *pnWritten = m_pStableBuffer->GetSize(); + + xnOSLeaveCriticalSection(&m_hLock); + + return XN_STATUS_OK; +} + + diff --git a/Source/XnDDK/XnFrameBufferManager.h b/Source/XnDDK/XnFrameBufferManager.h index fafa842..79c335d 100644 --- a/Source/XnDDK/XnFrameBufferManager.h +++ b/Source/XnDDK/XnFrameBufferManager.h @@ -1,80 +1,80 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_MULTI_FRAME_BUFFER_H__ -#define __XN_MULTI_FRAME_BUFFER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include "XnBufferPool.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -class XN_DDK_CPP_API XnFrameBufferManager -{ -public: - XnFrameBufferManager(XnBufferPool* pBufferPool); - ~XnFrameBufferManager(); - - XnStatus Init(XnUInt32 nBufferSize); - XnStatus Reallocate(XnUInt32 nBufferSize); - void Free(); - - inline XnBuffer* GetWriteBuffer() - { - // NOTE: no need to lock buffer, as we assume the same thread is the one that is responsible - // for marking working buffer as stable. - return m_pWorkingBuffer; - } - - void MarkWriteBufferAsStable(XnUInt64 nTimestamp, XnUInt32* pnFrameID); - - void ReadLastStableBuffer(XnBuffer** ppBuffer, XnUInt64* pnTimestamp, XnUInt32* pnFrameID); - - XnStatus CopyLastStableBuffer(void* pDest, XnUInt32 nDestSize, XnUInt32* pnWritten); - - inline XnUInt32 GetLastFrameID() const { return m_nStableFrameID; } - - XN_DECLARE_EVENT_2ARG(NewFrameEvent, NewFrameEventInterface, XnFrameBufferManager*, pTripleBuffer, XnUInt64, nTimestamp); - NewFrameEventInterface& OnNewFrameEvent() { return m_NewFrameEvent; } - -private: - XnBufferPool* m_pBufferPool; - XnBuffer* m_pWorkingBuffer; - XnBuffer* m_pStableBuffer; - XnUInt32 m_nStableFrameID; - XnUInt64 m_nStableTimestamp; - NewFrameEvent m_NewFrameEvent; - XN_CRITICAL_SECTION_HANDLE m_hLock; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_MULTI_FRAME_BUFFER_H__ +#define __XN_MULTI_FRAME_BUFFER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include "XnBufferPool.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +class XN_DDK_CPP_API XnFrameBufferManager +{ +public: + XnFrameBufferManager(XnBufferPool* pBufferPool); + ~XnFrameBufferManager(); + + XnStatus Init(XnUInt32 nBufferSize); + XnStatus Reallocate(XnUInt32 nBufferSize); + void Free(); + + inline XnBuffer* GetWriteBuffer() + { + // NOTE: no need to lock buffer, as we assume the same thread is the one that is responsible + // for marking working buffer as stable. + return m_pWorkingBuffer; + } + + void MarkWriteBufferAsStable(XnUInt64 nTimestamp, XnUInt32* pnFrameID); + + void ReadLastStableBuffer(XnBuffer** ppBuffer, XnUInt64* pnTimestamp, XnUInt32* pnFrameID); + + XnStatus CopyLastStableBuffer(void* pDest, XnUInt32 nDestSize, XnUInt32* pnWritten); + + inline XnUInt32 GetLastFrameID() const { return m_nStableFrameID; } + + XN_DECLARE_EVENT_2ARG(NewFrameEvent, NewFrameEventInterface, XnFrameBufferManager*, pTripleBuffer, XnUInt64, nTimestamp); + NewFrameEventInterface& OnNewFrameEvent() { return m_NewFrameEvent; } + +private: + XnBufferPool* m_pBufferPool; + XnBuffer* m_pWorkingBuffer; + XnBuffer* m_pStableBuffer; + XnUInt32 m_nStableFrameID; + XnUInt64 m_nStableTimestamp; + NewFrameEvent m_NewFrameEvent; + XN_CRITICAL_SECTION_HANDLE m_hLock; +}; + #endif //__XN_MULTI_FRAME_BUFFER_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnFrameStream.cpp b/Source/XnDDK/XnFrameStream.cpp index 15370a4..5a08670 100644 --- a/Source/XnDDK/XnFrameStream.cpp +++ b/Source/XnDDK/XnFrameStream.cpp @@ -1,259 +1,259 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameStream.h" -#include "XnStreamDataInternal.h" -#include "XnSimpleBufferPool.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFrameStream::XnFrameStream(const XnChar* csType, const XnChar* csName) : - XnDeviceStream(csType, csName), - m_IsFrameStream(XN_STREAM_PROPERTY_IS_FRAME_BASED, TRUE), - m_FPS(XN_STREAM_PROPERTY_FPS, 0), - m_LastRawFrame(XN_STREAM_PROPERTY_LAST_RAW_FRAME), - m_nLastReadFrame(0), - m_bTripleBufferReallocated(FALSE), - m_pBufferManager(NULL), - m_pBufferPool(NULL), - m_bPoolAllocated(FALSE) -{ - m_FPS.UpdateSetCallback(SetFPSCallback, this); - m_LastRawFrame.UpdateGetCallback(GetLastRawFrameCallback, this); -} - -XnStatus XnFrameStream::SetBufferPool(XnBufferPool* pBufferPool) -{ - // we only allow this if no buffer pool exists - if (m_pBufferPool != NULL) - { - return XN_STATUS_ERROR; - } - - m_pBufferPool = pBufferPool; - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnDeviceStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_ADD_PROPERTIES(this, &m_IsFrameStream, &m_FPS, &m_LastRawFrame); - - XnCallbackHandle hDummy; - - // be notified when required size changes - nRetVal = RequiredSizeProperty().OnChangeEvent().Register(RequiredSizeChangedCallback, this, &hDummy); - XN_IS_STATUS_OK(nRetVal); - - if (m_pBufferPool == NULL) - { - XN_VALIDATE_NEW(m_pBufferPool, XnSimpleBufferPool, 3); - m_bPoolAllocated = TRUE; - } - - // allocate buffer manager - XN_VALIDATE_NEW(m_pBufferManager, XnFrameBufferManager, m_pBufferPool); - - nRetVal = m_pBufferManager->Init(GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - // register for new data events - nRetVal = m_pBufferManager->OnNewFrameEvent().Register(OnTripleBufferNewData, this, &hDummy); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::Free() -{ - if (m_pBufferManager != NULL) - { - XN_DELETE(m_pBufferManager); - m_pBufferManager = NULL; - } - - if (m_bPoolAllocated && m_pBufferPool != NULL) - { - XN_DELETE(m_pBufferPool); - m_pBufferPool = NULL; - m_bPoolAllocated = FALSE; - } - - XnDeviceStream::Free(); - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::CreateStreamData(XnStreamData** ppStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamData* pStreamData; - - // we create a StreamData object with no buffer allocated. The buffer will just be - // a pointer to the triple buffer - nRetVal = XnStreamDataCreateNoBuffer(&pStreamData, GetName()); - XN_IS_STATUS_OK(nRetVal); - - // However, we don't want the user to get a null pointer, even if no new frame yet, - // so we'll initialize the data with one of the buffers - nRetVal = m_pBufferPool->GetBuffer(&pStreamData->pInternal->pLockedBuffer); - if (nRetVal != XN_STATUS_OK) - { - XnStreamDataDestroy(&pStreamData); - return (nRetVal); - } - - pStreamData->pData = (void*)pStreamData->pInternal->pLockedBuffer->GetData(); - - *ppStreamData = pStreamData; - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::SetFPS(XnUInt32 nFPS) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_FPS.UnsafeUpdateValue(nFPS); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::OnRequiredSizeChanging() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ReallocTripleFrameBuffer(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::ReallocTripleFrameBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pBufferManager->Reallocate(GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - m_bTripleBufferReallocated = TRUE; - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::Read(XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceStream::Read(pStreamData); - XN_IS_STATUS_OK(nRetVal); - - m_bTripleBufferReallocated = FALSE; - - return (XN_STATUS_OK); -} - -XnStatus XnFrameStream::ReadImpl(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // release previous buffer - m_pBufferPool->DecRef(pStreamOutput->pInternal->pLockedBuffer); - - m_pBufferManager->ReadLastStableBuffer( - &pStreamOutput->pInternal->pLockedBuffer, - &pStreamOutput->nTimestamp, - &pStreamOutput->nFrameID); - - pStreamOutput->pData = (void*)pStreamOutput->pInternal->pLockedBuffer->GetData(); - pStreamOutput->nDataSize = pStreamOutput->pInternal->pLockedBuffer->GetSize(); - pStreamOutput->nFrameID = ++m_nLastReadFrame; - - nRetVal = PostProcessFrame(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnFrameStream::HandleNoNewData(XnStreamData* pStreamOutput) -{ -/* // No new data, but if triple buffer was reallocated, we want the user buffer to be replaced - // (so that it has a buffer with a size that matches what he expects, even if no new data in it) - if (m_bTripleBufferReallocated && !pStreamOutput->pInternal->bAllocated) - { - XnFrameBuffer* pStableBuffer = m_pBufferManager->ReadLastStableBuffer(); - pStreamOutput->pData = (void*)pStableBuffer->DataBuf.GetData(); - } -*/ - return XN_STATUS_OK; -} - -XnStatus XnFrameStream::GetLastRawFrame(XnDynamicSizeBuffer* pBuffer) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pBufferManager->CopyLastStableBuffer(pBuffer->pData, pBuffer->nMaxSize, &pBuffer->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnFrameStream::SetFPSCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) -{ - XnFrameStream* pThis = (XnFrameStream*)pCookie; - return pThis->SetFPS((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnFrameStream::RequiredSizeChangedCallback(const XnProperty* pSenser, void* pCookie) -{ - XnFrameStream* pThis = (XnFrameStream*)pCookie; - return pThis->OnRequiredSizeChanging(); -} - -void XN_CALLBACK_TYPE XnFrameStream::OnTripleBufferNewData(XnFrameBufferManager* pTripleBuffer, XnUInt64 nTimestamp, void* pCookie) -{ - XnFrameStream* pThis = (XnFrameStream*)pCookie; - pThis->NewDataAvailable(nTimestamp, pThis->m_nLastReadFrame + 1); -} - -XnStatus XN_CALLBACK_TYPE XnFrameStream::GetLastRawFrameCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnDynamicSizeBuffer); - XnFrameStream* pThis = (XnFrameStream*)pCookie; - XnDynamicSizeBuffer* pBuffer = (XnDynamicSizeBuffer*)gbValue.pData; - return pThis->GetLastRawFrame(pBuffer); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameStream.h" +#include "XnStreamDataInternal.h" +#include "XnSimpleBufferPool.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFrameStream::XnFrameStream(const XnChar* csType, const XnChar* csName) : + XnDeviceStream(csType, csName), + m_IsFrameStream(XN_STREAM_PROPERTY_IS_FRAME_BASED, TRUE), + m_FPS(XN_STREAM_PROPERTY_FPS, 0), + m_LastRawFrame(XN_STREAM_PROPERTY_LAST_RAW_FRAME), + m_nLastReadFrame(0), + m_bTripleBufferReallocated(FALSE), + m_pBufferManager(NULL), + m_pBufferPool(NULL), + m_bPoolAllocated(FALSE) +{ + m_FPS.UpdateSetCallback(SetFPSCallback, this); + m_LastRawFrame.UpdateGetCallback(GetLastRawFrameCallback, this); +} + +XnStatus XnFrameStream::SetBufferPool(XnBufferPool* pBufferPool) +{ + // we only allow this if no buffer pool exists + if (m_pBufferPool != NULL) + { + return XN_STATUS_ERROR; + } + + m_pBufferPool = pBufferPool; + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnDeviceStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_ADD_PROPERTIES(this, &m_IsFrameStream, &m_FPS, &m_LastRawFrame); + + XnCallbackHandle hDummy; + + // be notified when required size changes + nRetVal = RequiredSizeProperty().OnChangeEvent().Register(RequiredSizeChangedCallback, this, &hDummy); + XN_IS_STATUS_OK(nRetVal); + + if (m_pBufferPool == NULL) + { + XN_VALIDATE_NEW(m_pBufferPool, XnSimpleBufferPool, 3); + m_bPoolAllocated = TRUE; + } + + // allocate buffer manager + XN_VALIDATE_NEW(m_pBufferManager, XnFrameBufferManager, m_pBufferPool); + + nRetVal = m_pBufferManager->Init(GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + // register for new data events + nRetVal = m_pBufferManager->OnNewFrameEvent().Register(OnTripleBufferNewData, this, &hDummy); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::Free() +{ + if (m_pBufferManager != NULL) + { + XN_DELETE(m_pBufferManager); + m_pBufferManager = NULL; + } + + if (m_bPoolAllocated && m_pBufferPool != NULL) + { + XN_DELETE(m_pBufferPool); + m_pBufferPool = NULL; + m_bPoolAllocated = FALSE; + } + + XnDeviceStream::Free(); + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::CreateStreamData(XnStreamData** ppStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamData* pStreamData; + + // we create a StreamData object with no buffer allocated. The buffer will just be + // a pointer to the triple buffer + nRetVal = XnStreamDataCreateNoBuffer(&pStreamData, GetName()); + XN_IS_STATUS_OK(nRetVal); + + // However, we don't want the user to get a null pointer, even if no new frame yet, + // so we'll initialize the data with one of the buffers + nRetVal = m_pBufferPool->GetBuffer(&pStreamData->pInternal->pLockedBuffer); + if (nRetVal != XN_STATUS_OK) + { + XnStreamDataDestroy(&pStreamData); + return (nRetVal); + } + + pStreamData->pData = (void*)pStreamData->pInternal->pLockedBuffer->GetData(); + + *ppStreamData = pStreamData; + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::SetFPS(XnUInt32 nFPS) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_FPS.UnsafeUpdateValue(nFPS); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::OnRequiredSizeChanging() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ReallocTripleFrameBuffer(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::ReallocTripleFrameBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pBufferManager->Reallocate(GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + m_bTripleBufferReallocated = TRUE; + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::Read(XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceStream::Read(pStreamData); + XN_IS_STATUS_OK(nRetVal); + + m_bTripleBufferReallocated = FALSE; + + return (XN_STATUS_OK); +} + +XnStatus XnFrameStream::ReadImpl(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // release previous buffer + m_pBufferPool->DecRef(pStreamOutput->pInternal->pLockedBuffer); + + m_pBufferManager->ReadLastStableBuffer( + &pStreamOutput->pInternal->pLockedBuffer, + &pStreamOutput->nTimestamp, + &pStreamOutput->nFrameID); + + pStreamOutput->pData = (void*)pStreamOutput->pInternal->pLockedBuffer->GetData(); + pStreamOutput->nDataSize = pStreamOutput->pInternal->pLockedBuffer->GetSize(); + pStreamOutput->nFrameID = ++m_nLastReadFrame; + + nRetVal = PostProcessFrame(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnFrameStream::HandleNoNewData(XnStreamData* pStreamOutput) +{ +/* // No new data, but if triple buffer was reallocated, we want the user buffer to be replaced + // (so that it has a buffer with a size that matches what he expects, even if no new data in it) + if (m_bTripleBufferReallocated && !pStreamOutput->pInternal->bAllocated) + { + XnFrameBuffer* pStableBuffer = m_pBufferManager->ReadLastStableBuffer(); + pStreamOutput->pData = (void*)pStableBuffer->DataBuf.GetData(); + } +*/ + return XN_STATUS_OK; +} + +XnStatus XnFrameStream::GetLastRawFrame(XnDynamicSizeBuffer* pBuffer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pBufferManager->CopyLastStableBuffer(pBuffer->pData, pBuffer->nMaxSize, &pBuffer->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnFrameStream::SetFPSCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) +{ + XnFrameStream* pThis = (XnFrameStream*)pCookie; + return pThis->SetFPS((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnFrameStream::RequiredSizeChangedCallback(const XnProperty* pSenser, void* pCookie) +{ + XnFrameStream* pThis = (XnFrameStream*)pCookie; + return pThis->OnRequiredSizeChanging(); +} + +void XN_CALLBACK_TYPE XnFrameStream::OnTripleBufferNewData(XnFrameBufferManager* pTripleBuffer, XnUInt64 nTimestamp, void* pCookie) +{ + XnFrameStream* pThis = (XnFrameStream*)pCookie; + pThis->NewDataAvailable(nTimestamp, pThis->m_nLastReadFrame + 1); +} + +XnStatus XN_CALLBACK_TYPE XnFrameStream::GetLastRawFrameCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnDynamicSizeBuffer); + XnFrameStream* pThis = (XnFrameStream*)pCookie; + XnDynamicSizeBuffer* pBuffer = (XnDynamicSizeBuffer*)gbValue.pData; + return pThis->GetLastRawFrame(pBuffer); +} diff --git a/Source/XnDDK/XnFrameStream.h b/Source/XnDDK/XnFrameStream.h index 51be57d..9324f25 100644 --- a/Source/XnDDK/XnFrameStream.h +++ b/Source/XnDDK/XnFrameStream.h @@ -1,114 +1,114 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FRAME_STREAM_H__ -#define __XN_FRAME_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceStream.h" -#include "XnFrameBufferManager.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a stream that is frame-based. */ -class XN_DDK_CPP_API XnFrameStream : public XnDeviceStream -{ -public: - XnFrameStream(const XnChar* csType, const XnChar* csName); - ~XnFrameStream() { Free(); } - - XnStatus SetBufferPool(XnBufferPool* pBufferPool); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnUInt32 GetFPS() const { return (XnUInt32)m_FPS.GetValue(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - XnStatus CreateStreamData(XnStreamData** ppStreamData); - XnStatus Read(XnStreamData* pStreamOutput); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnFrameBufferManager* GetTripleBuffer() { return m_pBufferManager; } - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& FPSProperty() { return m_FPS; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetFPS(XnUInt32 nFPS); - - //--------------------------------------------------------------------------- - // Virtual Methods - //--------------------------------------------------------------------------- - virtual XnStatus PostProcessFrame(XnStreamData* pFrameData) { return XN_STATUS_OK; } - virtual XnStatus ReallocTripleFrameBuffer(); - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus ReadImpl(XnStreamData* pStreamOutput); - XnStatus HandleNoNewData(XnStreamData* pStreamOutput); - -private: - XnStatus OnRequiredSizeChanging(); - XnStatus GetLastRawFrame(XnDynamicSizeBuffer* gbValue); - - static XnStatus XN_CALLBACK_TYPE SetFPSCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE RequiredSizeChangedCallback(const XnProperty* pSenser, void* pCookie); - static void XN_CALLBACK_TYPE OnTripleBufferNewData(XnFrameBufferManager* pTripleBuffer, XnUInt64 nTimestamp, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetLastRawFrameCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnFrameBufferManager* m_pBufferManager; - XnBufferPool* m_pBufferPool; - XnBool m_bPoolAllocated; - - XnUInt32 m_nLastReadFrame; // the ID that was given - - XnActualIntProperty m_IsFrameStream; - XnActualIntProperty m_FPS; - XnGeneralProperty m_LastRawFrame; - XnBool m_bTripleBufferReallocated; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FRAME_STREAM_H__ +#define __XN_FRAME_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceStream.h" +#include "XnFrameBufferManager.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a stream that is frame-based. */ +class XN_DDK_CPP_API XnFrameStream : public XnDeviceStream +{ +public: + XnFrameStream(const XnChar* csType, const XnChar* csName); + ~XnFrameStream() { Free(); } + + XnStatus SetBufferPool(XnBufferPool* pBufferPool); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnUInt32 GetFPS() const { return (XnUInt32)m_FPS.GetValue(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + XnStatus CreateStreamData(XnStreamData** ppStreamData); + XnStatus Read(XnStreamData* pStreamOutput); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnFrameBufferManager* GetTripleBuffer() { return m_pBufferManager; } + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& FPSProperty() { return m_FPS; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetFPS(XnUInt32 nFPS); + + //--------------------------------------------------------------------------- + // Virtual Methods + //--------------------------------------------------------------------------- + virtual XnStatus PostProcessFrame(XnStreamData* pFrameData) { return XN_STATUS_OK; } + virtual XnStatus ReallocTripleFrameBuffer(); + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus ReadImpl(XnStreamData* pStreamOutput); + XnStatus HandleNoNewData(XnStreamData* pStreamOutput); + +private: + XnStatus OnRequiredSizeChanging(); + XnStatus GetLastRawFrame(XnDynamicSizeBuffer* gbValue); + + static XnStatus XN_CALLBACK_TYPE SetFPSCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE RequiredSizeChangedCallback(const XnProperty* pSenser, void* pCookie); + static void XN_CALLBACK_TYPE OnTripleBufferNewData(XnFrameBufferManager* pTripleBuffer, XnUInt64 nTimestamp, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetLastRawFrameCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnFrameBufferManager* m_pBufferManager; + XnBufferPool* m_pBufferPool; + XnBool m_bPoolAllocated; + + XnUInt32 m_nLastReadFrame; // the ID that was given + + XnActualIntProperty m_IsFrameStream; + XnActualIntProperty m_FPS; + XnGeneralProperty m_LastRawFrame; + XnBool m_bTripleBufferReallocated; +}; + #endif //__XN_FRAME_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnGeneralProperty.cpp b/Source/XnDDK/XnGeneralProperty.cpp index e1b58ab..f4582c6 100644 --- a/Source/XnDDK/XnGeneralProperty.cpp +++ b/Source/XnDDK/XnGeneralProperty.cpp @@ -1,88 +1,88 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnGeneralProperty.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnGeneralProperty::XnGeneralProperty(const XnChar* strName, XnGeneralBuffer* pValueHolder /* = NULL */, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */ ) : - XnProperty(XN_PROPERTY_TYPE_GENERAL, pValueHolder, strName, strModule), - m_pReadFromFileFunc(pReadFromFileFunc) -{ -} - -XnStatus XnGeneralProperty::CopyValueImpl(void* pDest, const void* pSource) const -{ - return XnGeneralBufferCopy((XnGeneralBuffer*)pDest, (const XnGeneralBuffer*)pSource); -} - -XnBool XnGeneralProperty::IsEqual(const void* pValue1, const void* pValue2) const -{ - const XnGeneralBuffer* pgb1 = (const XnGeneralBuffer*)pValue1; - const XnGeneralBuffer* pgb2 = (const XnGeneralBuffer*)pValue2; - - if (pgb1->nDataSize != pgb2->nDataSize) - return FALSE; - - return (memcmp(pgb1->pData, pgb2->pData, pgb1->nDataSize) == 0); -} - -XnStatus XnGeneralProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) -{ - SetFuncPtr pCallback = (SetFuncPtr)pFunc; - return pCallback(this, *(const XnGeneralBuffer*)pValue, pCookie); -} - -XnStatus XnGeneralProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const -{ - GetFuncPtr pCallback = (GetFuncPtr)pFunc; - return pCallback(this, *(const XnGeneralBuffer*)pValue, pCookie); -} - -XnStatus XnGeneralProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_pReadFromFileFunc != NULL) - { - nRetVal = m_pReadFromFileFunc(this, csINIFile, csSection); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnGeneralProperty::AddToPropertySet(XnPropertySet* pSet) -{ - return (XN_STATUS_ERROR); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnGeneralProperty.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnGeneralProperty::XnGeneralProperty(const XnChar* strName, XnGeneralBuffer* pValueHolder /* = NULL */, ReadValueFromFileFuncPtr pReadFromFileFunc /* = NULL */, const XnChar* strModule /* = "" */ ) : + XnProperty(XN_PROPERTY_TYPE_GENERAL, pValueHolder, strName, strModule), + m_pReadFromFileFunc(pReadFromFileFunc) +{ +} + +XnStatus XnGeneralProperty::CopyValueImpl(void* pDest, const void* pSource) const +{ + return XnGeneralBufferCopy((XnGeneralBuffer*)pDest, (const XnGeneralBuffer*)pSource); +} + +XnBool XnGeneralProperty::IsEqual(const void* pValue1, const void* pValue2) const +{ + const XnGeneralBuffer* pgb1 = (const XnGeneralBuffer*)pValue1; + const XnGeneralBuffer* pgb2 = (const XnGeneralBuffer*)pValue2; + + if (pgb1->nDataSize != pgb2->nDataSize) + return FALSE; + + return (memcmp(pgb1->pData, pgb2->pData, pgb1->nDataSize) == 0); +} + +XnStatus XnGeneralProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) +{ + SetFuncPtr pCallback = (SetFuncPtr)pFunc; + return pCallback(this, *(const XnGeneralBuffer*)pValue, pCookie); +} + +XnStatus XnGeneralProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const +{ + GetFuncPtr pCallback = (GetFuncPtr)pFunc; + return pCallback(this, *(const XnGeneralBuffer*)pValue, pCookie); +} + +XnStatus XnGeneralProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pReadFromFileFunc != NULL) + { + nRetVal = m_pReadFromFileFunc(this, csINIFile, csSection); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnGeneralProperty::AddToPropertySet(XnPropertySet* pSet) +{ + return (XN_STATUS_ERROR); +} diff --git a/Source/XnDDK/XnGeneralProperty.h b/Source/XnDDK/XnGeneralProperty.h index 82ee343..036c985 100644 --- a/Source/XnDDK/XnGeneralProperty.h +++ b/Source/XnDDK/XnGeneralProperty.h @@ -1,94 +1,94 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_GENERAL_PROPERTY_H__ -#define __XN_GENERAL_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type general. -*/ -class XN_DDK_CPP_API XnGeneralProperty : public XnProperty -{ -public: - typedef XnStatus (XN_CALLBACK_TYPE* ReadValueFromFileFuncPtr)(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); - - XnGeneralProperty(const XnChar* strName, XnGeneralBuffer* pValueHolder = NULL, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - - inline XnStatus SetValue(const XnGeneralBuffer& gbValue) - { - return XnProperty::SetValue(&gbValue); - } - - inline XnStatus GetValue(const XnGeneralBuffer& gbValue) const - { - return XnProperty::GetValue((void*)&gbValue); - } - - inline XnStatus UnsafeUpdateValue(const XnGeneralBuffer& gbValue) - { - return XnProperty::UnsafeUpdateValue(&gbValue); - } - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); - } - - XnStatus AddToPropertySet(XnPropertySet* pSet); - -protected: - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; - virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; - virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); - virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; - virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); - -private: - ReadValueFromFileFuncPtr m_pReadFromFileFunc; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_GENERAL_PROPERTY_H__ +#define __XN_GENERAL_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type general. +*/ +class XN_DDK_CPP_API XnGeneralProperty : public XnProperty +{ +public: + typedef XnStatus (XN_CALLBACK_TYPE* ReadValueFromFileFuncPtr)(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); + + XnGeneralProperty(const XnChar* strName, XnGeneralBuffer* pValueHolder = NULL, ReadValueFromFileFuncPtr pReadFromFileFunc = NULL, const XnChar* strModule = ""); + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + + inline XnStatus SetValue(const XnGeneralBuffer& gbValue) + { + return XnProperty::SetValue(&gbValue); + } + + inline XnStatus GetValue(const XnGeneralBuffer& gbValue) const + { + return XnProperty::GetValue((void*)&gbValue); + } + + inline XnStatus UnsafeUpdateValue(const XnGeneralBuffer& gbValue) + { + return XnProperty::UnsafeUpdateValue(&gbValue); + } + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); + } + + XnStatus AddToPropertySet(XnPropertySet* pSet); + +protected: + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; + virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; + virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); + virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; + virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); + +private: + ReadValueFromFileFuncPtr m_pReadFromFileFunc; +}; + #endif //__XN_GENERAL_PROPERTY_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnIRStream.cpp b/Source/XnDDK/XnIRStream.cpp index 9a69e06..9b40db1 100644 --- a/Source/XnDDK/XnIRStream.cpp +++ b/Source/XnDDK/XnIRStream.cpp @@ -1,39 +1,39 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnIRStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnIRStream::XnIRStream(const XnChar* csName, XnBool bAllowCustomResolutions) : - XnPixelStream(XN_STREAM_TYPE_IR, csName, bAllowCustomResolutions) -{ -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnIRStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnIRStream::XnIRStream(const XnChar* csName, XnBool bAllowCustomResolutions) : + XnPixelStream(XN_STREAM_TYPE_IR, csName, bAllowCustomResolutions) +{ +} diff --git a/Source/XnDDK/XnIRStream.h b/Source/XnDDK/XnIRStream.h index 8c3acd4..037791b 100644 --- a/Source/XnDDK/XnIRStream.h +++ b/Source/XnDDK/XnIRStream.h @@ -1,46 +1,46 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IR_STREAM_H__ -#define __XN_IR_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a base class for an image stream. */ -class XN_DDK_CPP_API XnIRStream : public XnPixelStream -{ -public: - XnIRStream(const XnChar* csName, XnBool bAllowCustomResolutions); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IR_STREAM_H__ +#define __XN_IR_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a base class for an image stream. */ +class XN_DDK_CPP_API XnIRStream : public XnPixelStream +{ +public: + XnIRStream(const XnChar* csName, XnBool bAllowCustomResolutions); +}; + #endif //__XN_IR_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnImageStream.cpp b/Source/XnDDK/XnImageStream.cpp index 558abcb..4a4c5c4 100644 --- a/Source/XnDDK/XnImageStream.cpp +++ b/Source/XnDDK/XnImageStream.cpp @@ -1,39 +1,39 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnImageStream::XnImageStream(const XnChar* csName, XnBool bAllowCustomResolutions) : - XnPixelStream(XN_STREAM_TYPE_IMAGE, csName, bAllowCustomResolutions) -{ -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnImageStream::XnImageStream(const XnChar* csName, XnBool bAllowCustomResolutions) : + XnPixelStream(XN_STREAM_TYPE_IMAGE, csName, bAllowCustomResolutions) +{ +} diff --git a/Source/XnDDK/XnImageStream.h b/Source/XnDDK/XnImageStream.h index a5313eb..ac7268e 100644 --- a/Source/XnDDK/XnImageStream.h +++ b/Source/XnDDK/XnImageStream.h @@ -1,46 +1,46 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IMAGE_STREAM_H__ -#define __XN_IMAGE_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a base class for an image stream. */ -class XN_DDK_CPP_API XnImageStream : public XnPixelStream -{ -public: - XnImageStream(const XnChar* csName, XnBool bAllowCustomResolutions); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IMAGE_STREAM_H__ +#define __XN_IMAGE_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a base class for an image stream. */ +class XN_DDK_CPP_API XnImageStream : public XnPixelStream +{ +public: + XnImageStream(const XnChar* csName, XnBool bAllowCustomResolutions); +}; + #endif //__XN_IMAGE_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnIntProperty.cpp b/Source/XnDDK/XnIntProperty.cpp index b56ef65..b6f4da1 100644 --- a/Source/XnDDK/XnIntProperty.cpp +++ b/Source/XnDDK/XnIntProperty.cpp @@ -1,102 +1,102 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnIntProperty.h" -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnIntProperty::XnIntProperty(const XnChar* strName, XnUInt64* pValueHolder /* = NULL */, const XnChar* strModule /* = "" */ ) : - XnProperty(XN_PROPERTY_TYPE_INTEGER, pValueHolder, strName, strModule) -{ -} - -XnStatus XnIntProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nValue; - - nRetVal = xnOSReadIntFromINI(csINIFile, csSection, GetName(), &nValue); - if (nRetVal == XN_STATUS_OK) - { - nRetVal = SetValue(nValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnIntProperty::CopyValueImpl(void* pDest, const void* pSource) const -{ - (*(XnUInt64*)pDest) = (*(const XnUInt64*)pSource); - return XN_STATUS_OK; -} - -XnBool XnIntProperty::IsEqual(const void* pValue1, const void* pValue2) const -{ - return (*(XnUInt64*)pValue1) == (*(XnUInt64*)pValue2); -} - -XnStatus XnIntProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) -{ - SetFuncPtr pCallback = (SetFuncPtr)pFunc; - return pCallback(this, *(const XnUInt64*)pValue, pCookie); -} - -XnStatus XnIntProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const -{ - GetFuncPtr pCallback = (GetFuncPtr)pFunc; - return pCallback(this, (XnUInt64*)pValue, pCookie); -} - -XnBool XnIntProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const -{ - sprintf(csValue, "%llu", *(XnUInt64*)pValue); - return TRUE; -} - -XnStatus XnIntProperty::AddToPropertySet(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nValue; - nRetVal = GetValue(&nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, GetModule(), GetName(), nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnIntProperty.h" +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnIntProperty::XnIntProperty(const XnChar* strName, XnUInt64* pValueHolder /* = NULL */, const XnChar* strModule /* = "" */ ) : + XnProperty(XN_PROPERTY_TYPE_INTEGER, pValueHolder, strName, strModule) +{ +} + +XnStatus XnIntProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nValue; + + nRetVal = xnOSReadIntFromINI(csINIFile, csSection, GetName(), &nValue); + if (nRetVal == XN_STATUS_OK) + { + nRetVal = SetValue(nValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnIntProperty::CopyValueImpl(void* pDest, const void* pSource) const +{ + (*(XnUInt64*)pDest) = (*(const XnUInt64*)pSource); + return XN_STATUS_OK; +} + +XnBool XnIntProperty::IsEqual(const void* pValue1, const void* pValue2) const +{ + return (*(XnUInt64*)pValue1) == (*(XnUInt64*)pValue2); +} + +XnStatus XnIntProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) +{ + SetFuncPtr pCallback = (SetFuncPtr)pFunc; + return pCallback(this, *(const XnUInt64*)pValue, pCookie); +} + +XnStatus XnIntProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const +{ + GetFuncPtr pCallback = (GetFuncPtr)pFunc; + return pCallback(this, (XnUInt64*)pValue, pCookie); +} + +XnBool XnIntProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const +{ + sprintf(csValue, "%llu", *(XnUInt64*)pValue); + return TRUE; +} + +XnStatus XnIntProperty::AddToPropertySet(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nValue; + nRetVal = GetValue(&nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, GetModule(), GetName(), nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnIntProperty.h b/Source/XnDDK/XnIntProperty.h index 8e7f264..a4153b5 100644 --- a/Source/XnDDK/XnIntProperty.h +++ b/Source/XnDDK/XnIntProperty.h @@ -1,91 +1,91 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_INT_PROPERTY_H__ -#define __XN_INT_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type integer. -*/ -class XN_DDK_CPP_API XnIntProperty : public XnProperty -{ -public: - XnIntProperty(const XnChar* strName, XnUInt64* pValueHolder = NULL, const XnChar* strModule = ""); - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie); - - inline XnStatus SetValue(XnUInt64 nValue) - { - return XnProperty::SetValue(&nValue); - } - - inline XnStatus GetValue(XnUInt64* pnValue) const - { - XN_VALIDATE_OUTPUT_PTR(pnValue); - return XnProperty::GetValue(pnValue); - } - - XnStatus UnsafeUpdateValue(XnUInt64 nValue) - { - return XnProperty::UnsafeUpdateValue(&nValue); - } - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); - } - - virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); - - XnStatus AddToPropertySet(XnPropertySet* pSet); - -protected: - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; - virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; - virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); - virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; - virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; -}; - -#endif //__XN_INT_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_INT_PROPERTY_H__ +#define __XN_INT_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type integer. +*/ +class XN_DDK_CPP_API XnIntProperty : public XnProperty +{ +public: + XnIntProperty(const XnChar* strName, XnUInt64* pValueHolder = NULL, const XnChar* strModule = ""); + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie); + + inline XnStatus SetValue(XnUInt64 nValue) + { + return XnProperty::SetValue(&nValue); + } + + inline XnStatus GetValue(XnUInt64* pnValue) const + { + XN_VALIDATE_OUTPUT_PTR(pnValue); + return XnProperty::GetValue(pnValue); + } + + XnStatus UnsafeUpdateValue(XnUInt64 nValue) + { + return XnProperty::UnsafeUpdateValue(&nValue); + } + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); + } + + virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); + + XnStatus AddToPropertySet(XnPropertySet* pSet); + +protected: + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; + virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; + virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); + virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; + virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; +}; + +#endif //__XN_INT_PROPERTY_H__ diff --git a/Source/XnDDK/XnIntPropertySynchronizer.cpp b/Source/XnDDK/XnIntPropertySynchronizer.cpp index 0cc726b..51ed426 100644 --- a/Source/XnDDK/XnIntPropertySynchronizer.cpp +++ b/Source/XnDDK/XnIntPropertySynchronizer.cpp @@ -1,123 +1,123 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnIntPropertySynchronizer.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnIntSynchronizerCookie -{ -public: - XnIntSynchronizerCookie(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc) : - pSource(pSource), pDestination(pDestination), pConvertFunc(pConvertFunc) - {} - - XnIntProperty* pSource; - XnIntProperty* pDestination; - XnIntPropertyConvertCallback pConvertFunc; - XnCallbackHandle hCallback; -}; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnIntPropertySynchronizer::XnIntPropertySynchronizer() -{ -} - -XnIntPropertySynchronizer::~XnIntPropertySynchronizer() -{ - for (XnList::Iterator it = m_Cookies.begin(); it != m_Cookies.end(); ++it) - { - XnIntSynchronizerCookie* pSynchData = (XnIntSynchronizerCookie*)*it; - pSynchData->pSource->OnChangeEvent().Unregister(pSynchData->hCallback); - XN_DELETE(pSynchData); - } -} - -XnStatus XN_CALLBACK_TYPE IntPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get the property current value - XnIntProperty* pIntProp = (XnIntProperty*)pSender; - - XnUInt64 nNewValue; - nRetVal = pIntProp->GetValue(&nNewValue); - XN_IS_STATUS_OK(nRetVal); - - XnIntSynchronizerCookie* pSynchData = (XnIntSynchronizerCookie*)pCookie; - - XnUInt64 nDestValue; - - // convert the value if needed - if (pSynchData->pConvertFunc != NULL) - { - nRetVal = pSynchData->pConvertFunc(nNewValue, &nDestValue); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nDestValue = nNewValue; - } - - // now set the new value - nRetVal = pSynchData->pDestination->UnsafeUpdateValue(nDestValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnIntPropertySynchronizer::RegisterSynchronization(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnIntSynchronizerCookie* pCookie; - XN_VALIDATE_NEW(pCookie, XnIntSynchronizerCookie, pSource, pDestination, pConvertFunc); - - nRetVal = m_Cookies.AddFirst(pCookie); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pCookie); - return (nRetVal); - } - - nRetVal = pSource->OnChangeEvent().Register(IntPropertyValueChangedCallback, pCookie, &pCookie->hCallback); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pCookie); - m_Cookies.Remove(m_Cookies.begin()); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnIntPropertySynchronizer.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnIntSynchronizerCookie +{ +public: + XnIntSynchronizerCookie(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc) : + pSource(pSource), pDestination(pDestination), pConvertFunc(pConvertFunc) + {} + + XnIntProperty* pSource; + XnIntProperty* pDestination; + XnIntPropertyConvertCallback pConvertFunc; + XnCallbackHandle hCallback; +}; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnIntPropertySynchronizer::XnIntPropertySynchronizer() +{ +} + +XnIntPropertySynchronizer::~XnIntPropertySynchronizer() +{ + for (XnList::Iterator it = m_Cookies.begin(); it != m_Cookies.end(); ++it) + { + XnIntSynchronizerCookie* pSynchData = (XnIntSynchronizerCookie*)*it; + pSynchData->pSource->OnChangeEvent().Unregister(pSynchData->hCallback); + XN_DELETE(pSynchData); + } +} + +XnStatus XN_CALLBACK_TYPE IntPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get the property current value + XnIntProperty* pIntProp = (XnIntProperty*)pSender; + + XnUInt64 nNewValue; + nRetVal = pIntProp->GetValue(&nNewValue); + XN_IS_STATUS_OK(nRetVal); + + XnIntSynchronizerCookie* pSynchData = (XnIntSynchronizerCookie*)pCookie; + + XnUInt64 nDestValue; + + // convert the value if needed + if (pSynchData->pConvertFunc != NULL) + { + nRetVal = pSynchData->pConvertFunc(nNewValue, &nDestValue); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nDestValue = nNewValue; + } + + // now set the new value + nRetVal = pSynchData->pDestination->UnsafeUpdateValue(nDestValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnIntPropertySynchronizer::RegisterSynchronization(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnIntSynchronizerCookie* pCookie; + XN_VALIDATE_NEW(pCookie, XnIntSynchronizerCookie, pSource, pDestination, pConvertFunc); + + nRetVal = m_Cookies.AddFirst(pCookie); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pCookie); + return (nRetVal); + } + + nRetVal = pSource->OnChangeEvent().Register(IntPropertyValueChangedCallback, pCookie, &pCookie->hCallback); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pCookie); + m_Cookies.Remove(m_Cookies.begin()); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnIntPropertySynchronizer.h b/Source/XnDDK/XnIntPropertySynchronizer.h index 0201c48..324fed6 100644 --- a/Source/XnDDK/XnIntPropertySynchronizer.h +++ b/Source/XnDDK/XnIntPropertySynchronizer.h @@ -1,53 +1,53 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_INT_PROPERTY_SYNCHRONIZER_H__ -#define __XN_INT_PROPERTY_SYNCHRONIZER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef XnStatus (XN_CALLBACK_TYPE* XnIntPropertyConvertCallback)(XnUInt64 nSourceValue, XnUInt64* pnDestValue); - -class XN_DDK_CPP_API XnIntPropertySynchronizer -{ -public: - XnIntPropertySynchronizer(); - ~XnIntPropertySynchronizer(); - - XnStatus RegisterSynchronization(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc = NULL); - -private: - XnList m_Cookies; -}; - -#endif //__XN_INT_PROPERTY_SYNCHRONIZER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_INT_PROPERTY_SYNCHRONIZER_H__ +#define __XN_INT_PROPERTY_SYNCHRONIZER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef XnStatus (XN_CALLBACK_TYPE* XnIntPropertyConvertCallback)(XnUInt64 nSourceValue, XnUInt64* pnDestValue); + +class XN_DDK_CPP_API XnIntPropertySynchronizer +{ +public: + XnIntPropertySynchronizer(); + ~XnIntPropertySynchronizer(); + + XnStatus RegisterSynchronization(XnIntProperty* pSource, XnIntProperty* pDestination, XnIntPropertyConvertCallback pConvertFunc = NULL); + +private: + XnList m_Cookies; +}; + +#endif //__XN_INT_PROPERTY_SYNCHRONIZER_H__ diff --git a/Source/XnDDK/XnPixelStream.cpp b/Source/XnDDK/XnPixelStream.cpp index db0f2cc..9ccea69 100644 --- a/Source/XnDDK/XnPixelStream.cpp +++ b/Source/XnDDK/XnPixelStream.cpp @@ -1,463 +1,463 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnPixelStream.h" -#include -#include -#include - -//--------------------------------------------------------------------------- -// XnPixelStream -//--------------------------------------------------------------------------- -XnPixelStream::XnPixelStream(const XnChar* csType, const XnChar* csName, XnBool bAllowCustomResolutions) : - XnFrameStream(csType, csName), - m_IsPixelStream(XN_STREAM_PROPERTY_IS_PIXEL_BASED, TRUE), - m_Resolution(XN_STREAM_PROPERTY_RESOLUTION, XN_RESOLUTION_VGA), - m_XRes(XN_STREAM_PROPERTY_X_RES, XN_VGA_X_RES), - m_YRes(XN_STREAM_PROPERTY_Y_RES, XN_VGA_Y_RES), - m_BytesPerPixel(XN_STREAM_PROPERTY_BYTES_PER_PIXEL), - m_Cropping(XN_STREAM_PROPERTY_CROPPING, &m_CroppingData, sizeof(XnCropping), ReadCroppingFromFileCallback), - m_bAllowCustomResolutions(bAllowCustomResolutions) -{ - xnOSMemSet(&m_CroppingData, 0, sizeof(XnCropping)); -} - -XnStatus XnPixelStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnFrameStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - // update set callbacks - m_Resolution.UpdateSetCallback(SetResolutionCallback, this); - m_XRes.UpdateSetCallback(SetXResCallback, this); - m_YRes.UpdateSetCallback(SetYResCallback, this); - m_Cropping.UpdateSetCallback(SetCroppingCallback, this); - - // add properties - XN_VALIDATE_ADD_PROPERTIES(this, &m_IsPixelStream, &m_Resolution, &m_XRes, &m_YRes, &m_BytesPerPixel, &m_Cropping); - - // register required size properties - nRetVal = RegisterRequiredSizeProperty(&m_XRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RegisterRequiredSizeProperty(&m_YRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RegisterRequiredSizeProperty(&m_BytesPerPixel); - XN_IS_STATUS_OK(nRetVal); - - // register for important properties - XnCallbackHandle hDummyCallback; - nRetVal = m_Resolution.OnChangeEvent().Register(ResolutionValueChangedCallback, this, &hDummyCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = OutputFormatProperty().OnChangeEvent().Register(OutputFormatValueChangedCallback, this, &hDummyCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_XRes.OnChangeEvent().Register(FixCroppingCallback, this, &hDummyCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_YRes.OnChangeEvent().Register(FixCroppingCallback, this, &hDummyCallback); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::SetResolution(XnResolutions nResolution) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Resolution.UnsafeUpdateValue(nResolution); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::SetXRes(XnUInt32 nXRes) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_bAllowCustomResolutions) - { - // just update the value - nRetVal = m_XRes.UnsafeUpdateValue(nXRes); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // instead of updating XRes, we'll update the resolution, and XRes will be updated - // via ValueChanged event - XnResolutions nRes; - - switch (nXRes) - { - case XN_QVGA_X_RES: - nRes = XN_RESOLUTION_QVGA; - break; - case XN_VGA_X_RES: - nRes = XN_RESOLUTION_VGA; - break; - case XN_SXGA_X_RES: - nRes = XN_RESOLUTION_SXGA; - break; - case XN_UXGA_X_RES: - nRes = XN_RESOLUTION_UXGA; - break; - default: - return (XN_STATUS_DEVICE_BAD_PARAM); - } - - nRetVal = SetResolution(nRes); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::SetYRes(XnUInt32 nYRes) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_bAllowCustomResolutions) - { - // just update the value - nRetVal = m_YRes.UnsafeUpdateValue(nYRes); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // instead of updating YRes, we'll update the resolution, and YRes will be updated - // via ValueChanged event - XnResolutions nRes; - - switch (nYRes) - { - case XN_QVGA_Y_RES: - nRes = XN_RESOLUTION_QVGA; - break; - case XN_VGA_Y_RES: - nRes = XN_RESOLUTION_VGA; - break; - case XN_SXGA_Y_RES: - nRes = XN_RESOLUTION_SXGA; - break; - case XN_UXGA_Y_RES: - nRes = XN_RESOLUTION_UXGA; - break; - default: - return (XN_STATUS_DEVICE_BAD_PARAM); - } - - nRetVal = SetResolution(nRes); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::SetCropping(const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ValidateCropping(pCropping); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Cropping.UnsafeUpdateValue(XN_PACK_GENERAL_BUFFER(*(XnCropping*)pCropping)); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::ValidateCropping(const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (pCropping->bEnabled) - { - if (pCropping->nXOffset > GetXRes() || - XnUInt32(pCropping->nXOffset + pCropping->nXSize) > GetXRes() || - pCropping->nYOffset > GetYRes() || - XnUInt32(pCropping->nYOffset + pCropping->nYSize) > GetYRes()) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Cropping values do not match stream resolution!"); - } - - if (pCropping->nXSize == 0 || pCropping->nYSize == 0) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Cannot set a cropping window of zero size!"); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::OnResolutionChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_Resolution.GetValue() != XN_RESOLUTION_CUSTOM) - { - // update XRes and YRes accordingly - XnUInt32 nXRes; - XnUInt32 nYRes; - - switch (m_Resolution.GetValue()) - { - case XN_RESOLUTION_QVGA: - nXRes = XN_QVGA_X_RES; - nYRes = XN_QVGA_Y_RES; - break; - case XN_RESOLUTION_VGA: - nXRes = XN_VGA_X_RES; - nYRes = XN_VGA_Y_RES; - break; - case XN_RESOLUTION_UXGA: - nXRes = XN_UXGA_X_RES; - nYRes = XN_UXGA_Y_RES; - break; - case XN_RESOLUTION_SXGA: - nXRes = XN_SXGA_X_RES; - nYRes = XN_SXGA_Y_RES; - break; - } - - nRetVal = m_XRes.UnsafeUpdateValue(nXRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_YRes.UnsafeUpdateValue(nYRes); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::OnOutputFormatChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // update the bytes-per-pixel value - XnUInt32 nBytesPerPixel; - - switch (GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - nBytesPerPixel = sizeof(XnUInt16); - break; - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - nBytesPerPixel = sizeof(XnDepthPixel); - break; - case XN_OUTPUT_FORMAT_GRAYSCALE8: - nBytesPerPixel = sizeof(XnUInt8); - break; - case XN_OUTPUT_FORMAT_GRAYSCALE16: - nBytesPerPixel = sizeof(XnUInt16); - break; - case XN_OUTPUT_FORMAT_YUV422: - // YUV422 is actually 4 bytes for every 2 pixels - nBytesPerPixel = sizeof(XnUChar) * 2; - break; - case XN_OUTPUT_FORMAT_RGB24: - nBytesPerPixel = sizeof(XnUChar) * 3; - break; - case XN_OUTPUT_FORMAT_JPEG: - // size is unknown. - nBytesPerPixel = 1; - break; - default: - return (XN_STATUS_DEVICE_BAD_PARAM); - } - - nRetVal = m_BytesPerPixel.UnsafeUpdateValue(nBytesPerPixel); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::FixCropping() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnCropping cropping = *GetCropping(); - if (cropping.nXOffset > GetXRes() || - cropping.nYOffset > GetYRes() || - XnUInt32(cropping.nXOffset + cropping.nXSize) > GetXRes() || - XnUInt32(cropping.nYOffset + cropping.nYSize) > GetYRes()) - { - // disable it - cropping.bEnabled = FALSE; - nRetVal = SetCropping(&cropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const -{ - *pnRequiredSize = GetXRes() * GetYRes() * GetBytesPerPixel(); - return XN_STATUS_OK; -} - -XnStatus XnPixelStream::ReadImpl(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first read - nRetVal = XnFrameStream::ReadImpl(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - // now crop - xnOSEnterCriticalSection(GetLock()); - XnCropping cropping = *GetCropping(); - xnOSLeaveCriticalSection(GetLock()); - - if (cropping.bEnabled) - { - nRetVal = CropImpl(pStreamOutput, &cropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnPixelStream::Mirror(XnStreamData* pStreamOutput) const -{ - XnUInt32 nXRes = GetCropping()->bEnabled ? GetCropping()->nXSize : GetXRes(); - return XnFormatsMirrorPixelData(GetOutputFormat(), (XnUChar*)pStreamOutput->pData, pStreamOutput->nDataSize, nXRes); -} - -XnStatus XnPixelStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUChar* pPixelData = (XnUChar*)pStreamOutput->pData; - XnUInt32 nCurDataSize = 0; - - for (XnUInt32 y = pCropping->nYOffset; y < XnUInt32(pCropping->nYOffset + pCropping->nYSize); ++y) - { - XnUChar* pOrigLine = &pPixelData[y * GetXRes() * GetBytesPerPixel()]; - - // move line - xnOSMemCopy(pPixelData + nCurDataSize, pOrigLine + pCropping->nXOffset * GetBytesPerPixel(), pCropping->nXSize * GetBytesPerPixel()); - nCurDataSize += pCropping->nXSize * GetBytesPerPixel(); - } - - // update size - pStreamOutput->nDataSize = nCurDataSize; - - return XN_STATUS_OK; -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::ResolutionValueChangedCallback(const XnProperty* pSenser, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->OnResolutionChanged(); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::OutputFormatValueChangedCallback(const XnProperty* pSenser, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->OnOutputFormatChanged(); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::FixCroppingCallback(const XnProperty* pSenser, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->FixCropping(); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::SetResolutionCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->SetResolution((XnResolutions)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::SetXResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->SetXRes((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::SetYResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - return pStream->SetYRes((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::SetCroppingCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XnPixelStream* pStream = (XnPixelStream*)pCookie; - if (gbValue.nDataSize != sizeof(XnCropping)) - { - return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; - } - - return pStream->SetCropping((XnCropping*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnPixelStream::ReadCroppingFromFileCallback(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read section name - XnChar csCroppingSection[XN_FILE_MAX_PATH]; - sprintf(csCroppingSection, "%s.Cropping", csSection); - - // read cropping values - XnUInt32 nOffsetX; - XnUInt32 nOffsetY; - XnUInt32 nSizeX; - XnUInt32 nSizeY; - XnUInt32 bEnabled; - - // only if all values are here - if (XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetX", &nOffsetX) && - XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetY", &nOffsetY) && - XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeX", &nSizeX) && - XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeY", &nSizeY) && - XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "Enabled", &bEnabled)) - { - XnCropping Cropping; - Cropping.nXOffset = nOffsetX; - Cropping.nYOffset = nOffsetY; - Cropping.nXSize = nSizeX; - Cropping.nYSize = nSizeY; - Cropping.bEnabled = bEnabled; - - // set value - nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(Cropping)); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnPixelStream.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// XnPixelStream +//--------------------------------------------------------------------------- +XnPixelStream::XnPixelStream(const XnChar* csType, const XnChar* csName, XnBool bAllowCustomResolutions) : + XnFrameStream(csType, csName), + m_IsPixelStream(XN_STREAM_PROPERTY_IS_PIXEL_BASED, TRUE), + m_Resolution(XN_STREAM_PROPERTY_RESOLUTION, XN_RESOLUTION_VGA), + m_XRes(XN_STREAM_PROPERTY_X_RES, XN_VGA_X_RES), + m_YRes(XN_STREAM_PROPERTY_Y_RES, XN_VGA_Y_RES), + m_BytesPerPixel(XN_STREAM_PROPERTY_BYTES_PER_PIXEL), + m_Cropping(XN_STREAM_PROPERTY_CROPPING, &m_CroppingData, sizeof(XnCropping), ReadCroppingFromFileCallback), + m_bAllowCustomResolutions(bAllowCustomResolutions) +{ + xnOSMemSet(&m_CroppingData, 0, sizeof(XnCropping)); +} + +XnStatus XnPixelStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnFrameStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + // update set callbacks + m_Resolution.UpdateSetCallback(SetResolutionCallback, this); + m_XRes.UpdateSetCallback(SetXResCallback, this); + m_YRes.UpdateSetCallback(SetYResCallback, this); + m_Cropping.UpdateSetCallback(SetCroppingCallback, this); + + // add properties + XN_VALIDATE_ADD_PROPERTIES(this, &m_IsPixelStream, &m_Resolution, &m_XRes, &m_YRes, &m_BytesPerPixel, &m_Cropping); + + // register required size properties + nRetVal = RegisterRequiredSizeProperty(&m_XRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RegisterRequiredSizeProperty(&m_YRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RegisterRequiredSizeProperty(&m_BytesPerPixel); + XN_IS_STATUS_OK(nRetVal); + + // register for important properties + XnCallbackHandle hDummyCallback; + nRetVal = m_Resolution.OnChangeEvent().Register(ResolutionValueChangedCallback, this, &hDummyCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = OutputFormatProperty().OnChangeEvent().Register(OutputFormatValueChangedCallback, this, &hDummyCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_XRes.OnChangeEvent().Register(FixCroppingCallback, this, &hDummyCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_YRes.OnChangeEvent().Register(FixCroppingCallback, this, &hDummyCallback); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::SetResolution(XnResolutions nResolution) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Resolution.UnsafeUpdateValue(nResolution); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::SetXRes(XnUInt32 nXRes) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_bAllowCustomResolutions) + { + // just update the value + nRetVal = m_XRes.UnsafeUpdateValue(nXRes); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // instead of updating XRes, we'll update the resolution, and XRes will be updated + // via ValueChanged event + XnResolutions nRes; + + switch (nXRes) + { + case XN_QVGA_X_RES: + nRes = XN_RESOLUTION_QVGA; + break; + case XN_VGA_X_RES: + nRes = XN_RESOLUTION_VGA; + break; + case XN_SXGA_X_RES: + nRes = XN_RESOLUTION_SXGA; + break; + case XN_UXGA_X_RES: + nRes = XN_RESOLUTION_UXGA; + break; + default: + return (XN_STATUS_DEVICE_BAD_PARAM); + } + + nRetVal = SetResolution(nRes); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::SetYRes(XnUInt32 nYRes) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_bAllowCustomResolutions) + { + // just update the value + nRetVal = m_YRes.UnsafeUpdateValue(nYRes); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // instead of updating YRes, we'll update the resolution, and YRes will be updated + // via ValueChanged event + XnResolutions nRes; + + switch (nYRes) + { + case XN_QVGA_Y_RES: + nRes = XN_RESOLUTION_QVGA; + break; + case XN_VGA_Y_RES: + nRes = XN_RESOLUTION_VGA; + break; + case XN_SXGA_Y_RES: + nRes = XN_RESOLUTION_SXGA; + break; + case XN_UXGA_Y_RES: + nRes = XN_RESOLUTION_UXGA; + break; + default: + return (XN_STATUS_DEVICE_BAD_PARAM); + } + + nRetVal = SetResolution(nRes); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::SetCropping(const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ValidateCropping(pCropping); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Cropping.UnsafeUpdateValue(XN_PACK_GENERAL_BUFFER(*(XnCropping*)pCropping)); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::ValidateCropping(const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (pCropping->bEnabled) + { + if (pCropping->nXOffset > GetXRes() || + XnUInt32(pCropping->nXOffset + pCropping->nXSize) > GetXRes() || + pCropping->nYOffset > GetYRes() || + XnUInt32(pCropping->nYOffset + pCropping->nYSize) > GetYRes()) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Cropping values do not match stream resolution!"); + } + + if (pCropping->nXSize == 0 || pCropping->nYSize == 0) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DDK, "Cannot set a cropping window of zero size!"); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::OnResolutionChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_Resolution.GetValue() != XN_RESOLUTION_CUSTOM) + { + // update XRes and YRes accordingly + XnUInt32 nXRes; + XnUInt32 nYRes; + + switch (m_Resolution.GetValue()) + { + case XN_RESOLUTION_QVGA: + nXRes = XN_QVGA_X_RES; + nYRes = XN_QVGA_Y_RES; + break; + case XN_RESOLUTION_VGA: + nXRes = XN_VGA_X_RES; + nYRes = XN_VGA_Y_RES; + break; + case XN_RESOLUTION_UXGA: + nXRes = XN_UXGA_X_RES; + nYRes = XN_UXGA_Y_RES; + break; + case XN_RESOLUTION_SXGA: + nXRes = XN_SXGA_X_RES; + nYRes = XN_SXGA_Y_RES; + break; + } + + nRetVal = m_XRes.UnsafeUpdateValue(nXRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_YRes.UnsafeUpdateValue(nYRes); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::OnOutputFormatChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // update the bytes-per-pixel value + XnUInt32 nBytesPerPixel; + + switch (GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + nBytesPerPixel = sizeof(XnUInt16); + break; + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + nBytesPerPixel = sizeof(XnDepthPixel); + break; + case XN_OUTPUT_FORMAT_GRAYSCALE8: + nBytesPerPixel = sizeof(XnUInt8); + break; + case XN_OUTPUT_FORMAT_GRAYSCALE16: + nBytesPerPixel = sizeof(XnUInt16); + break; + case XN_OUTPUT_FORMAT_YUV422: + // YUV422 is actually 4 bytes for every 2 pixels + nBytesPerPixel = sizeof(XnUChar) * 2; + break; + case XN_OUTPUT_FORMAT_RGB24: + nBytesPerPixel = sizeof(XnUChar) * 3; + break; + case XN_OUTPUT_FORMAT_JPEG: + // size is unknown. + nBytesPerPixel = 1; + break; + default: + return (XN_STATUS_DEVICE_BAD_PARAM); + } + + nRetVal = m_BytesPerPixel.UnsafeUpdateValue(nBytesPerPixel); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::FixCropping() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnCropping cropping = *GetCropping(); + if (cropping.nXOffset > GetXRes() || + cropping.nYOffset > GetYRes() || + XnUInt32(cropping.nXOffset + cropping.nXSize) > GetXRes() || + XnUInt32(cropping.nYOffset + cropping.nYSize) > GetYRes()) + { + // disable it + cropping.bEnabled = FALSE; + nRetVal = SetCropping(&cropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const +{ + *pnRequiredSize = GetXRes() * GetYRes() * GetBytesPerPixel(); + return XN_STATUS_OK; +} + +XnStatus XnPixelStream::ReadImpl(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first read + nRetVal = XnFrameStream::ReadImpl(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + // now crop + xnOSEnterCriticalSection(GetLock()); + XnCropping cropping = *GetCropping(); + xnOSLeaveCriticalSection(GetLock()); + + if (cropping.bEnabled) + { + nRetVal = CropImpl(pStreamOutput, &cropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnPixelStream::Mirror(XnStreamData* pStreamOutput) const +{ + XnUInt32 nXRes = GetCropping()->bEnabled ? GetCropping()->nXSize : GetXRes(); + return XnFormatsMirrorPixelData(GetOutputFormat(), (XnUChar*)pStreamOutput->pData, pStreamOutput->nDataSize, nXRes); +} + +XnStatus XnPixelStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUChar* pPixelData = (XnUChar*)pStreamOutput->pData; + XnUInt32 nCurDataSize = 0; + + for (XnUInt32 y = pCropping->nYOffset; y < XnUInt32(pCropping->nYOffset + pCropping->nYSize); ++y) + { + XnUChar* pOrigLine = &pPixelData[y * GetXRes() * GetBytesPerPixel()]; + + // move line + xnOSMemCopy(pPixelData + nCurDataSize, pOrigLine + pCropping->nXOffset * GetBytesPerPixel(), pCropping->nXSize * GetBytesPerPixel()); + nCurDataSize += pCropping->nXSize * GetBytesPerPixel(); + } + + // update size + pStreamOutput->nDataSize = nCurDataSize; + + return XN_STATUS_OK; +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::ResolutionValueChangedCallback(const XnProperty* pSenser, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->OnResolutionChanged(); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::OutputFormatValueChangedCallback(const XnProperty* pSenser, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->OnOutputFormatChanged(); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::FixCroppingCallback(const XnProperty* pSenser, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->FixCropping(); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::SetResolutionCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->SetResolution((XnResolutions)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::SetXResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->SetXRes((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::SetYResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + return pStream->SetYRes((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::SetCroppingCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XnPixelStream* pStream = (XnPixelStream*)pCookie; + if (gbValue.nDataSize != sizeof(XnCropping)) + { + return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; + } + + return pStream->SetCropping((XnCropping*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnPixelStream::ReadCroppingFromFileCallback(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read section name + XnChar csCroppingSection[XN_FILE_MAX_PATH]; + sprintf(csCroppingSection, "%s.Cropping", csSection); + + // read cropping values + XnUInt32 nOffsetX; + XnUInt32 nOffsetY; + XnUInt32 nSizeX; + XnUInt32 nSizeY; + XnUInt32 bEnabled; + + // only if all values are here + if (XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetX", &nOffsetX) && + XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetY", &nOffsetY) && + XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeX", &nSizeX) && + XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeY", &nSizeY) && + XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "Enabled", &bEnabled)) + { + XnCropping Cropping; + Cropping.nXOffset = nOffsetX; + Cropping.nYOffset = nOffsetY; + Cropping.nXSize = nSizeX; + Cropping.nYSize = nSizeY; + Cropping.bEnabled = bEnabled; + + // set value + nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(Cropping)); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnPixelStream.h b/Source/XnDDK/XnPixelStream.h index ff10b58..a4a0a0a 100644 --- a/Source/XnDDK/XnPixelStream.h +++ b/Source/XnDDK/XnPixelStream.h @@ -1,125 +1,125 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PIXEL_STREAM_H__ -#define __XN_PIXEL_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a stream that is pixel based (meaning, its output data is a matrix of data). */ -class XN_DDK_CPP_API XnPixelStream : public XnFrameStream -{ -public: - XnPixelStream(const XnChar* csType, const XnChar* csName, XnBool bAllowCustomResolutions); - ~XnPixelStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnResolutions GetResolution() const { return (XnResolutions)m_Resolution.GetValue(); } - inline XnUInt32 GetXRes() const { return (XnUInt32)m_XRes.GetValue(); } - inline XnUInt32 GetYRes() const { return (XnUInt32)m_YRes.GetValue(); } - inline XnUInt32 GetBytesPerPixel() const { return (XnUInt32)m_BytesPerPixel.GetValue(); } - inline const XnCropping* GetCropping() const { return (XnCropping*)m_Cropping.GetValue().pData; } - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& IsPixelStreamProperty() { return m_IsPixelStream; } - inline XnActualIntProperty& ResolutionProperty() { return m_Resolution; } - inline XnActualIntProperty& XResProperty() { return m_XRes; } - inline XnActualIntProperty& YResProperty() { return m_YRes; } - inline XnActualIntProperty& BytesPerPixelProperty() { return m_BytesPerPixel; } - inline XnActualGeneralProperty& CroppingProperty() { return m_Cropping; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetResolution(XnResolutions nResolution); - virtual XnStatus SetXRes(XnUInt32 nXRes); - virtual XnStatus SetYRes(XnUInt32 nYRes); - virtual XnStatus SetCropping(const XnCropping* pCropping); - - //--------------------------------------------------------------------------- - // Virtual Methods - //--------------------------------------------------------------------------- - - /** Crops the stream output. */ - virtual XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus ReadImpl(XnStreamData* pStreamOutput); - XnStatus Mirror(XnStreamData* pStreamOutput) const; - XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; - - XnStatus ValidateCropping(const XnCropping* pCropping); - -private: - XnStatus OnResolutionChanged(); - XnStatus OnOutputFormatChanged(); - XnStatus FixCropping(); - - static XnStatus XN_CALLBACK_TYPE SetResolutionCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetXResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetYResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetCroppingCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ResolutionValueChangedCallback(const XnProperty* pSenser, void* pCookie); - static XnStatus XN_CALLBACK_TYPE OutputFormatValueChangedCallback(const XnProperty* pSenser, void* pCookie); - static XnStatus XN_CALLBACK_TYPE FixCroppingCallback(const XnProperty* pSenser, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ReadCroppingFromFileCallback(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_IsPixelStream; - XnActualIntProperty m_Resolution; - XnActualIntProperty m_XRes; - XnActualIntProperty m_YRes; - XnActualIntProperty m_BytesPerPixel; - XnActualGeneralProperty m_Cropping; - - XnCropping m_CroppingData; - - XnBool m_bAllowCustomResolutions; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PIXEL_STREAM_H__ +#define __XN_PIXEL_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a stream that is pixel based (meaning, its output data is a matrix of data). */ +class XN_DDK_CPP_API XnPixelStream : public XnFrameStream +{ +public: + XnPixelStream(const XnChar* csType, const XnChar* csName, XnBool bAllowCustomResolutions); + ~XnPixelStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnResolutions GetResolution() const { return (XnResolutions)m_Resolution.GetValue(); } + inline XnUInt32 GetXRes() const { return (XnUInt32)m_XRes.GetValue(); } + inline XnUInt32 GetYRes() const { return (XnUInt32)m_YRes.GetValue(); } + inline XnUInt32 GetBytesPerPixel() const { return (XnUInt32)m_BytesPerPixel.GetValue(); } + inline const XnCropping* GetCropping() const { return (XnCropping*)m_Cropping.GetValue().pData; } + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& IsPixelStreamProperty() { return m_IsPixelStream; } + inline XnActualIntProperty& ResolutionProperty() { return m_Resolution; } + inline XnActualIntProperty& XResProperty() { return m_XRes; } + inline XnActualIntProperty& YResProperty() { return m_YRes; } + inline XnActualIntProperty& BytesPerPixelProperty() { return m_BytesPerPixel; } + inline XnActualGeneralProperty& CroppingProperty() { return m_Cropping; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetResolution(XnResolutions nResolution); + virtual XnStatus SetXRes(XnUInt32 nXRes); + virtual XnStatus SetYRes(XnUInt32 nYRes); + virtual XnStatus SetCropping(const XnCropping* pCropping); + + //--------------------------------------------------------------------------- + // Virtual Methods + //--------------------------------------------------------------------------- + + /** Crops the stream output. */ + virtual XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus ReadImpl(XnStreamData* pStreamOutput); + XnStatus Mirror(XnStreamData* pStreamOutput) const; + XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; + + XnStatus ValidateCropping(const XnCropping* pCropping); + +private: + XnStatus OnResolutionChanged(); + XnStatus OnOutputFormatChanged(); + XnStatus FixCropping(); + + static XnStatus XN_CALLBACK_TYPE SetResolutionCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetXResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetYResCallback(XnActualIntProperty* pSenser, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetCroppingCallback(XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ResolutionValueChangedCallback(const XnProperty* pSenser, void* pCookie); + static XnStatus XN_CALLBACK_TYPE OutputFormatValueChangedCallback(const XnProperty* pSenser, void* pCookie); + static XnStatus XN_CALLBACK_TYPE FixCroppingCallback(const XnProperty* pSenser, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ReadCroppingFromFileCallback(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_IsPixelStream; + XnActualIntProperty m_Resolution; + XnActualIntProperty m_XRes; + XnActualIntProperty m_YRes; + XnActualIntProperty m_BytesPerPixel; + XnActualGeneralProperty m_Cropping; + + XnCropping m_CroppingData; + + XnBool m_bAllowCustomResolutions; +}; + #endif //__XN_PIXEL_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnProperty.cpp b/Source/XnDDK/XnProperty.cpp index f84f329..0d89723 100644 --- a/Source/XnDDK/XnProperty.cpp +++ b/Source/XnDDK/XnProperty.cpp @@ -1,178 +1,178 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnProperty.h" -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnProperty::XnProperty(XnPropertyType Type, void* pValueHolder, const XnChar* strName, const XnChar* strModule) : - m_Type(Type), - m_pSetCallback(NULL), - m_pGetCallback(NULL), - m_pValueHolder(pValueHolder), - m_LogSeverity(XN_LOG_INFO) -{ - UpdateName(strModule, strName); -} - -XnProperty::~XnProperty() -{ -} - -void XnProperty::UpdateName(const XnChar* strModule, const XnChar* strName) -{ - strncpy(m_strModule, strModule, XN_DEVICE_MAX_STRING_LENGTH); - strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); -} - -XnStatus XnProperty::SetValue(const void* pValue) -{ - if (m_pSetCallback == NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_READ_ONLY, XN_MASK_DDK, "Property %s.%s is read only.", GetModule(), GetName()); - } - - if (m_LogSeverity != -1) - { - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - XnBool bValueString = FALSE; - - if (ConvertValueToString(strValue, pValue)) - { - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Setting %s.%s to %s...", GetModule(), GetName(), strValue); - } - else - { - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Setting %s.%s...", GetModule(), GetName()); - } - } - - XnBool bShouldSet = TRUE; - - if (!m_bAlwaysSet && IsActual() && IsEqual(m_pValueHolder, pValue)) - { - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "%s.%s value did not change.", GetModule(), GetName()); - } - else - { - XnStatus nRetVal = CallSetCallback(m_pSetCallback, pValue, m_pSetCallbackCookie); - if (nRetVal != XN_STATUS_OK) - { - if (m_LogSeverity != -1) - { - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Failed setting %s.%s: %s", GetModule(), GetName(), xnGetStatusString(nRetVal)); - } - return (nRetVal); - } - else - { - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "%s.%s was successfully set.", GetModule(), GetName()); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnProperty::GetValue(void* pValue) const -{ - if (m_pGetCallback == NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_WRITE_ONLY, XN_MASK_DDK, "Property %s.%s is write only.", GetModule(), GetName()); - } - - return CallGetCallback(m_pGetCallback, pValue, m_pGetCallbackCookie); -} - -XnStatus XnProperty::UnsafeUpdateValue(const void* pValue /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnBool bValueChanged = TRUE; - - if (IsActual()) - { - if (IsEqual(m_pValueHolder, pValue)) - { - bValueChanged = FALSE; - } - else - { - // update the value - nRetVal = CopyValueImpl(m_pValueHolder, pValue); - XN_IS_STATUS_OK(nRetVal); - } - } - - if (bValueChanged) - { - // print a message - if (m_LogSeverity != -1) - { - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - XnBool bValueString = FALSE; - - if (IsActual()) - { - bValueString = ConvertValueToString(strValue, pValue); - } - - xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Property %s.%s was changed%s%s.", GetModule(), GetName(), - bValueString ? " to " : "", bValueString ? strValue : ""); - } - - // raise the event - nRetVal = m_OnChangeEvent.Raise(this); - XN_IS_STATUS_OK(nRetVal); - } - - return XN_STATUS_OK; -} - -void XnProperty::UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) -{ - m_pSetCallback = pFunc; - m_pSetCallbackCookie = pCookie; -} - -void XnProperty::UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) -{ - m_pGetCallback = pFunc; - m_pGetCallbackCookie = pCookie; -} - -XnBool XnProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const -{ - return FALSE; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnProperty.h" +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnProperty::XnProperty(XnPropertyType Type, void* pValueHolder, const XnChar* strName, const XnChar* strModule) : + m_Type(Type), + m_pSetCallback(NULL), + m_pGetCallback(NULL), + m_pValueHolder(pValueHolder), + m_LogSeverity(XN_LOG_INFO) +{ + UpdateName(strModule, strName); +} + +XnProperty::~XnProperty() +{ +} + +void XnProperty::UpdateName(const XnChar* strModule, const XnChar* strName) +{ + strncpy(m_strModule, strModule, XN_DEVICE_MAX_STRING_LENGTH); + strncpy(m_strName, strName, XN_DEVICE_MAX_STRING_LENGTH); +} + +XnStatus XnProperty::SetValue(const void* pValue) +{ + if (m_pSetCallback == NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_READ_ONLY, XN_MASK_DDK, "Property %s.%s is read only.", GetModule(), GetName()); + } + + if (m_LogSeverity != -1) + { + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + XnBool bValueString = FALSE; + + if (ConvertValueToString(strValue, pValue)) + { + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Setting %s.%s to %s...", GetModule(), GetName(), strValue); + } + else + { + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Setting %s.%s...", GetModule(), GetName()); + } + } + + XnBool bShouldSet = TRUE; + + if (!m_bAlwaysSet && IsActual() && IsEqual(m_pValueHolder, pValue)) + { + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "%s.%s value did not change.", GetModule(), GetName()); + } + else + { + XnStatus nRetVal = CallSetCallback(m_pSetCallback, pValue, m_pSetCallbackCookie); + if (nRetVal != XN_STATUS_OK) + { + if (m_LogSeverity != -1) + { + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Failed setting %s.%s: %s", GetModule(), GetName(), xnGetStatusString(nRetVal)); + } + return (nRetVal); + } + else + { + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "%s.%s was successfully set.", GetModule(), GetName()); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnProperty::GetValue(void* pValue) const +{ + if (m_pGetCallback == NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROPERTY_WRITE_ONLY, XN_MASK_DDK, "Property %s.%s is write only.", GetModule(), GetName()); + } + + return CallGetCallback(m_pGetCallback, pValue, m_pGetCallbackCookie); +} + +XnStatus XnProperty::UnsafeUpdateValue(const void* pValue /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnBool bValueChanged = TRUE; + + if (IsActual()) + { + if (IsEqual(m_pValueHolder, pValue)) + { + bValueChanged = FALSE; + } + else + { + // update the value + nRetVal = CopyValueImpl(m_pValueHolder, pValue); + XN_IS_STATUS_OK(nRetVal); + } + } + + if (bValueChanged) + { + // print a message + if (m_LogSeverity != -1) + { + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + XnBool bValueString = FALSE; + + if (IsActual()) + { + bValueString = ConvertValueToString(strValue, pValue); + } + + xnLogWrite(XN_MASK_DDK, (XnLogSeverity)m_LogSeverity, __FILE__, __LINE__, "Property %s.%s was changed%s%s.", GetModule(), GetName(), + bValueString ? " to " : "", bValueString ? strValue : ""); + } + + // raise the event + nRetVal = m_OnChangeEvent.Raise(this); + XN_IS_STATUS_OK(nRetVal); + } + + return XN_STATUS_OK; +} + +void XnProperty::UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) +{ + m_pSetCallback = pFunc; + m_pSetCallbackCookie = pCookie; +} + +void XnProperty::UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) +{ + m_pGetCallback = pFunc; + m_pGetCallbackCookie = pCookie; +} + +XnBool XnProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const +{ + return FALSE; +} diff --git a/Source/XnDDK/XnProperty.h b/Source/XnDDK/XnProperty.h index adf7f66..b551304 100644 --- a/Source/XnDDK/XnProperty.h +++ b/Source/XnDDK/XnProperty.h @@ -1,143 +1,143 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PROPERTY_H__ -#define __XN_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* A holder for a property (a name and value pair). Note that this class should be inherited, and -* can not be used directly. -*/ -class XN_DDK_CPP_API XnProperty -{ -public: - /** - * Creates a new property. - * - * @param Type [in] Type of the property. - * @param pValueHolder [in] A pointer to the holder of the value. - * @param strName [in] Name of the property. - * @param strModule [in] Name of the module holding this property. - */ - XnProperty(XnPropertyType Type, void* pValueHolder, const XnChar* strName, const XnChar* strModule); - virtual ~XnProperty(); - - inline const XnChar* GetName() const { return m_strName; } - inline const XnChar* GetModule() const { return m_strModule; } - inline XnBool IsActual() const { return (m_pValueHolder != NULL); } - inline XnBool IsReadOnly() const { return (m_pGetCallback == NULL); } - inline XnPropertyType GetType() const { return m_Type; } - - XN_DECLARE_EVENT_1ARG_RETVAL(ChangeEvent, ChangeEventInterface, const XnProperty*, pSender); - - inline ChangeEventInterface& OnChangeEvent() { return m_OnChangeEvent; } - - /** Updates property name. */ - void UpdateName(const XnChar* strModule, const XnChar* strName); - - /** Updates the value of the property according to an INI file. */ - virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) = 0; - - typedef XnStatus (XN_CALLBACK_TYPE* OnValueChangedHandler)(const XnProperty* pSender, void* pCookie); - - /** Adds this property to the property set. */ - virtual XnStatus AddToPropertySet(XnPropertySet* pSet) = 0; - - /** Sets the log severity under which changes to the property are printed. */ - inline void SetLogSeverity(XnInt32 nSeverity) { m_LogSeverity = nSeverity; } - - /** When TRUE, the property will always call the set callback, even if value hasn't changed. */ - inline void SetAlwaysSet(XnBool bAlwaysSet) { m_bAlwaysSet = bAlwaysSet; } - -protected: - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnProperty* pSender, const void* pValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnProperty* pSender, void* pValue, void* pCookie); - - /** Sets the property value. */ - XnStatus SetValue(const void* pValue); - - /** Gets the property value. */ - XnStatus GetValue(void* pValue) const; - - /** Updates the value of the property without any checks. */ - XnStatus UnsafeUpdateValue(const void* pValue = NULL); - - /** Updates the set callback. */ - void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie); - - /** Updates the get callback. */ - void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie); - - virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const = 0; - virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const = 0; - virtual XnStatus CallSetCallback(SetFuncPtr pFunc, const void* pValue, void* pCookie) = 0; - virtual XnStatus CallGetCallback(GetFuncPtr pFunc, void* pValue, void* pCookie) const = 0; - virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; - - inline void* Value() const { return m_pValueHolder; } - -private: - XnChar m_strModule[XN_DEVICE_MAX_STRING_LENGTH]; // module name - XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; // property name - XnPropertyType m_Type; // property type - - // Set callback - SetFuncPtr m_pSetCallback; - void* m_pSetCallbackCookie; - - // Get callback - GetFuncPtr m_pGetCallback; - void* m_pGetCallbackCookie; - - void* m_pValueHolder; // a pointer to the storage of the property - - ChangeEvent m_OnChangeEvent; - - XnInt32 m_LogSeverity; - XnBool m_bAlwaysSet; -}; - -/** A property list */ -XN_DECLARE_LIST_DECL(XN_DDK_CPP_API, XnProperty*, XnPropertiesList) - -/** A hash table, mapping property name to the property */ -XN_DECLARE_STRINGS_HASH_DECL(XN_DDK_CPP_API, XnProperty*, XnPropertiesHash) - -#endif //__XN_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PROPERTY_H__ +#define __XN_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* A holder for a property (a name and value pair). Note that this class should be inherited, and +* can not be used directly. +*/ +class XN_DDK_CPP_API XnProperty +{ +public: + /** + * Creates a new property. + * + * @param Type [in] Type of the property. + * @param pValueHolder [in] A pointer to the holder of the value. + * @param strName [in] Name of the property. + * @param strModule [in] Name of the module holding this property. + */ + XnProperty(XnPropertyType Type, void* pValueHolder, const XnChar* strName, const XnChar* strModule); + virtual ~XnProperty(); + + inline const XnChar* GetName() const { return m_strName; } + inline const XnChar* GetModule() const { return m_strModule; } + inline XnBool IsActual() const { return (m_pValueHolder != NULL); } + inline XnBool IsReadOnly() const { return (m_pGetCallback == NULL); } + inline XnPropertyType GetType() const { return m_Type; } + + XN_DECLARE_EVENT_1ARG_RETVAL(ChangeEvent, ChangeEventInterface, const XnProperty*, pSender); + + inline ChangeEventInterface& OnChangeEvent() { return m_OnChangeEvent; } + + /** Updates property name. */ + void UpdateName(const XnChar* strModule, const XnChar* strName); + + /** Updates the value of the property according to an INI file. */ + virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) = 0; + + typedef XnStatus (XN_CALLBACK_TYPE* OnValueChangedHandler)(const XnProperty* pSender, void* pCookie); + + /** Adds this property to the property set. */ + virtual XnStatus AddToPropertySet(XnPropertySet* pSet) = 0; + + /** Sets the log severity under which changes to the property are printed. */ + inline void SetLogSeverity(XnInt32 nSeverity) { m_LogSeverity = nSeverity; } + + /** When TRUE, the property will always call the set callback, even if value hasn't changed. */ + inline void SetAlwaysSet(XnBool bAlwaysSet) { m_bAlwaysSet = bAlwaysSet; } + +protected: + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnProperty* pSender, const void* pValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnProperty* pSender, void* pValue, void* pCookie); + + /** Sets the property value. */ + XnStatus SetValue(const void* pValue); + + /** Gets the property value. */ + XnStatus GetValue(void* pValue) const; + + /** Updates the value of the property without any checks. */ + XnStatus UnsafeUpdateValue(const void* pValue = NULL); + + /** Updates the set callback. */ + void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie); + + /** Updates the get callback. */ + void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie); + + virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const = 0; + virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const = 0; + virtual XnStatus CallSetCallback(SetFuncPtr pFunc, const void* pValue, void* pCookie) = 0; + virtual XnStatus CallGetCallback(GetFuncPtr pFunc, void* pValue, void* pCookie) const = 0; + virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; + + inline void* Value() const { return m_pValueHolder; } + +private: + XnChar m_strModule[XN_DEVICE_MAX_STRING_LENGTH]; // module name + XnChar m_strName[XN_DEVICE_MAX_STRING_LENGTH]; // property name + XnPropertyType m_Type; // property type + + // Set callback + SetFuncPtr m_pSetCallback; + void* m_pSetCallbackCookie; + + // Get callback + GetFuncPtr m_pGetCallback; + void* m_pGetCallbackCookie; + + void* m_pValueHolder; // a pointer to the storage of the property + + ChangeEvent m_OnChangeEvent; + + XnInt32 m_LogSeverity; + XnBool m_bAlwaysSet; +}; + +/** A property list */ +XN_DECLARE_LIST_DECL(XN_DDK_CPP_API, XnProperty*, XnPropertiesList) + +/** A hash table, mapping property name to the property */ +XN_DECLARE_STRINGS_HASH_DECL(XN_DDK_CPP_API, XnProperty*, XnPropertiesHash) + +#endif //__XN_PROPERTY_H__ diff --git a/Source/XnDDK/XnPropertySet.cpp b/Source/XnDDK/XnPropertySet.cpp index 8301d7d..f641697 100644 --- a/Source/XnDDK/XnPropertySet.cpp +++ b/Source/XnDDK/XnPropertySet.cpp @@ -1,700 +1,700 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnPropertySetInternal.h" -#include -#include -#include "XnActualIntProperty.h" -#include "XnActualRealProperty.h" -#include "XnActualStringProperty.h" -#include "XnActualGeneralProperty.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -struct XnPropertySetModuleEnumerator -{ - XnBool bFirst; - XnPropertySetData* pModules; - XnPropertySetData::ConstIterator it; -}; - -struct XnPropertySetEnumerator -{ - XnBool bFirst; - XnPropertySetData* pModules; - XnPropertySetData::ConstIterator itModule; - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnActualPropertiesHash::ConstIterator itProp; -}; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XN_DDK_API XnStatus XnPropertySetCreate(XnPropertySet** ppSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OUTPUT_PTR(ppSet); - - XnPropertySet* pSet; - XN_VALIDATE_ALLOC(pSet, XnPropertySet); - - pSet->pData = XN_NEW(XnPropertySetData); - if (pSet->pData == NULL) - { - xnOSFree(pSet); - return XN_STATUS_ALLOC_FAILED; - } - - *ppSet = pSet; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetDestroy(XnPropertySet** ppSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(ppSet); - XN_VALIDATE_INPUT_PTR(*ppSet); - - XnPropertySet* pSet = (*ppSet); - - if (pSet->pData != NULL) - { - XnPropertySetClear(pSet); - XN_DELETE(pSet->pData); - } - - xnOSFree(pSet); - - *ppSet = NULL; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetClear(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - - while (!pSet->pData->IsEmpty()) - { - nRetVal = XnPropertySetRemoveModule(pSet, pSet->pData->begin().Key()); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetAddModule(XnPropertySet* pSet, const XnChar* strModuleName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - - XnActualPropertiesHash* pModule = NULL; - - // make sure this module doesn't already exists - nRetVal = pSet->pData->Get(strModuleName, pModule); - if (XN_STATUS_OK == nRetVal) - { - return XN_STATUS_DEVICE_MODULE_ALREADY_EXISTS; - } - - // doesn't exist. create a new one - XN_VALIDATE_NEW(pModule, XnActualPropertiesHash, strModuleName); - - nRetVal = XnPropertySetDataAttachModule(pSet->pData, strModuleName, pModule); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pModule); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetRemoveModule(XnPropertySet* pSet, const XnChar* strModuleName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - - XnActualPropertiesHash* pModule = NULL; - nRetVal = XnPropertySetDataDetachModule(pSet->pData, strModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // now free its memory - XN_DELETE(pModule); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetAddIntProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(strProperty); - - // get module - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - // add property - nRetVal = pModule->Add(strProperty, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetAddRealProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(strProperty); - - // get module - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - // add property - nRetVal = pModule->Add(strProperty, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetAddStringProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(strProperty); - XN_VALIDATE_INPUT_PTR(strValue); - - // get module - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - // add property - nRetVal = pModule->Add(strProperty, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetAddGeneralProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnGeneralBuffer* pgbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(strProperty); - XN_VALIDATE_INPUT_PTR(pgbValue); - - // get module - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - // add property - nRetVal = pModule->Add(strProperty, *pgbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetRemoveProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(strProperty); - - // get module - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - // remove the property - XnProperty* pProp; - nRetVal = pModule->Remove(strProperty); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetGetModuleEnumerator(const XnPropertySet* pSet, XnPropertySetModuleEnumerator** ppEnumerator) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_OUTPUT_PTR(ppEnumerator); - - XnPropertySetModuleEnumerator* pEnumer; - XN_VALIDATE_ALLOC(pEnumer, XnPropertySetModuleEnumerator); - - pEnumer->bFirst = TRUE; - pEnumer->it = pSet->pData->end(); - pEnumer->pModules = pSet->pData; - - *ppEnumerator = pEnumer; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorFree(XnPropertySetModuleEnumerator** ppEnumer) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(ppEnumer); - XN_VALIDATE_INPUT_PTR(*ppEnumer); - - xnOSFree(*ppEnumer); - *ppEnumer = NULL; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorMoveNext(XnPropertySetModuleEnumerator* pEnumerator, XnBool* pbEnd) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pbEnd); - - if (pEnumerator->bFirst) - { - pEnumerator->it = pEnumerator->pModules->begin(); - pEnumerator->bFirst = FALSE; - } - else if (pEnumerator->it == pEnumerator->pModules->end()) - { - return XN_STATUS_ILLEGAL_POSITION; - } - else - { - pEnumerator->it++; - } - - *pbEnd = (pEnumerator->it == pEnumerator->pModules->end()); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetModuleEnumeratorGetCurrent(const XnPropertySetModuleEnumerator* pEnumer, const XnChar** pstrModuleName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumer); - XN_VALIDATE_OUTPUT_PTR(pstrModuleName); - - if (pEnumer->it == pEnumer->pModules->end()) - { - return XN_STATUS_ILLEGAL_POSITION; - } - - *pstrModuleName = pEnumer->it.Key(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetGetEnumerator(const XnPropertySet* pSet, XnPropertySetEnumerator** ppEnumerator, const XnChar* strModule /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_OUTPUT_PTR(ppEnumerator); - - if (strModule != NULL) - { - // make sure module exists - XnPropertySetData::ConstIterator it = pSet->pData->end(); - nRetVal = pSet->pData->Find(strModule, it); - XN_IS_STATUS_OK(nRetVal); - } - - XnPropertySetEnumerator* pEnumer; - XN_VALIDATE_ALLOC(pEnumer, XnPropertySetEnumerator); - - pEnumer->bFirst = TRUE; - pEnumer->pModules = pSet->pData; - if (strModule != NULL) - { - strncpy(pEnumer->strModule, strModule, XN_DEVICE_MAX_STRING_LENGTH); - } - else - { - pEnumer->strModule[0] = '\0'; - } - - *ppEnumerator = pEnumer; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetFindProperty(const XnPropertySet* pSet, const XnChar* strModule, const XnChar* strProp, XnPropertySetEnumerator** ppEnumerator) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSet); - XN_VALIDATE_INPUT_PTR(strModule); - XN_VALIDATE_INPUT_PTR(strProp); - XN_VALIDATE_OUTPUT_PTR(ppEnumerator); - - // find module - XnPropertySetData::Iterator itModule = pSet->pData->end(); - nRetVal = pSet->pData->Find(strModule, itModule); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pModule = itModule.Value(); - - // find property - XnActualPropertiesHash::Iterator itProp = pModule->end(); - nRetVal = pModule->Find(strProp, itProp); - XN_IS_STATUS_OK(nRetVal); - - // create enumerator - XnPropertySetEnumerator* pEnumer; - XN_VALIDATE_ALLOC(pEnumer, XnPropertySetEnumerator); - - pEnumer->itModule = itModule; - pEnumer->itProp = itProp; - pEnumer->pModules = pSet->pData; - pEnumer->strModule[0] = '\0'; - pEnumer->bFirst = FALSE; - - *ppEnumerator = pEnumer; - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorFree(XnPropertySetEnumerator** ppEnumerator) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(ppEnumerator); - XN_VALIDATE_INPUT_PTR(*ppEnumerator); - - xnOSFree(*ppEnumerator); - *ppEnumerator = NULL; - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorMoveNext(XnPropertySetEnumerator* pEnumerator, XnBool* pbEnd) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pbEnd); - - *pbEnd = TRUE; - - if (pEnumerator->strModule[0] != '\0') // single module - { - if (pEnumerator->bFirst) - { - pEnumerator->bFirst = FALSE; - - // find this module - nRetVal = pEnumerator->pModules->Find(pEnumerator->strModule, pEnumerator->itModule); - if (nRetVal == XN_STATUS_NO_MATCH) - { - pEnumerator->itModule = pEnumerator->pModules->end(); - } - XN_IS_STATUS_OK(nRetVal); - - pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); - } - else if (pEnumerator->itProp == pEnumerator->itModule.Value()->end()) - { - return XN_STATUS_ILLEGAL_POSITION; - } - else - { - // advance prop iterator - pEnumerator->itProp++; - } - - *pbEnd = (pEnumerator->itProp == pEnumerator->itModule.Value()->end()); - } - else // all modules - { - if (pEnumerator->bFirst) - { - pEnumerator->bFirst = FALSE; - - // search for the first modules that has properties - pEnumerator->itModule = pEnumerator->pModules->begin(); - while (pEnumerator->itModule != pEnumerator->pModules->end() && pEnumerator->itModule.Value()->IsEmpty()) - { - pEnumerator->itModule++; - } - - // if we found one, take it's first property - if (pEnumerator->itModule != pEnumerator->pModules->end()) - { - pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); - *pbEnd = FALSE; - } - else - { - *pbEnd = TRUE; - } - } - else if (pEnumerator->itModule == pEnumerator->pModules->end()) - { - return XN_STATUS_ILLEGAL_POSITION; - } - else - { - // move to next one - pEnumerator->itProp++; - - // check if we reached end of module - if (pEnumerator->itProp == pEnumerator->itModule.Value()->end()) - { - // move to next module with properties - do - { - pEnumerator->itModule++; - } - while (pEnumerator->itModule != pEnumerator->pModules->end() && pEnumerator->itModule.Value()->IsEmpty()); - - // if we found one, take it's first property - if (pEnumerator->itModule != pEnumerator->pModules->end()) - { - pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); - *pbEnd = FALSE; - } - else - { - *pbEnd = TRUE; - } - } - else - { - *pbEnd = FALSE; - } - } - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorGetCurrentPropertyInfo(const XnPropertySetEnumerator* pEnumerator, XnPropertyType* pnType, const XnChar** pstrModule, const XnChar** pstrProp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pnType); - XN_VALIDATE_OUTPUT_PTR(pstrModule); - XN_VALIDATE_OUTPUT_PTR(pstrProp); - - XnProperty* pProp = pEnumerator->itProp.Value(); - *pnType = pProp->GetType(); - *pstrModule = pProp->GetModule(); - *pstrProp = pProp->GetName(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorGetIntValue(const XnPropertySetEnumerator* pEnumerator, XnUInt64* pnValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pnValue); - - XnProperty* pPropBase = pEnumerator->itProp.Value(); - if (pPropBase->GetType() != XN_PROPERTY_TYPE_INTEGER) - { - return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; - } - - XnActualIntProperty* pProp = (XnActualIntProperty*)pPropBase; - *pnValue = pProp->GetValue(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorGetRealValue(const XnPropertySetEnumerator* pEnumerator, XnDouble* pdValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pdValue); - - XnProperty* pPropBase = pEnumerator->itProp.Value(); - if (pPropBase->GetType() != XN_PROPERTY_TYPE_REAL) - { - return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; - } - - XnActualRealProperty* pProp = (XnActualRealProperty*)pPropBase; - *pdValue = pProp->GetValue(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorGetStringValue(const XnPropertySetEnumerator* pEnumerator, const XnChar** pstrValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pstrValue); - - XnProperty* pPropBase = pEnumerator->itProp.Value(); - if (pPropBase->GetType() != XN_PROPERTY_TYPE_STRING) - { - return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; - } - - XnActualStringProperty* pProp = (XnActualStringProperty*)pPropBase; - *pstrValue = pProp->GetValue(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetEnumeratorGetGeneralValue(const XnPropertySetEnumerator* pEnumerator, XnGeneralBuffer* pgbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pEnumerator); - XN_VALIDATE_OUTPUT_PTR(pgbValue); - - XnProperty* pPropBase = pEnumerator->itProp.Value(); - if (pPropBase->GetType() != XN_PROPERTY_TYPE_GENERAL) - { - return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; - } - - XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pPropBase; - *pgbValue = pProp->GetValue(); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetDataAttachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash* pModule) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSetData); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_INPUT_PTR(pModule); - - nRetVal = pSetData->Set(strModuleName, pModule); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetDataDetachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash** ppModule) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pSetData); - XN_VALIDATE_INPUT_PTR(strModuleName); - XN_VALIDATE_OUTPUT_PTR(ppModule); - - // remove it - nRetVal = pSetData->Remove(strModuleName, *ppModule); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnPropertySetCloneModule(XnPropertySet* pSource, XnPropertySet* pDest, const XnChar* strModule, const XnChar* strNewName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnActualPropertiesHash* pModuleProps; - nRetVal = pSource->pData->Get(strModule, pModuleProps); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddModule(pDest, strNewName); - XN_IS_STATUS_OK(nRetVal); - - for (XnActualPropertiesHash::ConstIterator it = pModuleProps->begin(); it != pModuleProps->end(); ++it) - { - XnProperty* pProp = it.Value(); - switch (pProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; - nRetVal = XnPropertySetAddIntProperty(pDest, strNewName, pIntProp->GetName(), pIntProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; - nRetVal = XnPropertySetAddRealProperty(pDest, strNewName, pRealProp->GetName(), pRealProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; - nRetVal = XnPropertySetAddStringProperty(pDest, strNewName, pStrProp->GetName(), pStrProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; - nRetVal = XnPropertySetAddGeneralProperty(pDest, strNewName, pGenProp->GetName(), &pGenProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d", pProp->GetType()); - } - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnPropertySetInternal.h" +#include +#include +#include "XnActualIntProperty.h" +#include "XnActualRealProperty.h" +#include "XnActualStringProperty.h" +#include "XnActualGeneralProperty.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +struct XnPropertySetModuleEnumerator +{ + XnBool bFirst; + XnPropertySetData* pModules; + XnPropertySetData::ConstIterator it; +}; + +struct XnPropertySetEnumerator +{ + XnBool bFirst; + XnPropertySetData* pModules; + XnPropertySetData::ConstIterator itModule; + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnActualPropertiesHash::ConstIterator itProp; +}; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XN_DDK_API XnStatus XnPropertySetCreate(XnPropertySet** ppSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OUTPUT_PTR(ppSet); + + XnPropertySet* pSet; + XN_VALIDATE_ALLOC(pSet, XnPropertySet); + + pSet->pData = XN_NEW(XnPropertySetData); + if (pSet->pData == NULL) + { + xnOSFree(pSet); + return XN_STATUS_ALLOC_FAILED; + } + + *ppSet = pSet; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetDestroy(XnPropertySet** ppSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(ppSet); + XN_VALIDATE_INPUT_PTR(*ppSet); + + XnPropertySet* pSet = (*ppSet); + + if (pSet->pData != NULL) + { + XnPropertySetClear(pSet); + XN_DELETE(pSet->pData); + } + + xnOSFree(pSet); + + *ppSet = NULL; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetClear(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + + while (!pSet->pData->IsEmpty()) + { + nRetVal = XnPropertySetRemoveModule(pSet, pSet->pData->begin().Key()); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetAddModule(XnPropertySet* pSet, const XnChar* strModuleName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + + XnActualPropertiesHash* pModule = NULL; + + // make sure this module doesn't already exists + nRetVal = pSet->pData->Get(strModuleName, pModule); + if (XN_STATUS_OK == nRetVal) + { + return XN_STATUS_DEVICE_MODULE_ALREADY_EXISTS; + } + + // doesn't exist. create a new one + XN_VALIDATE_NEW(pModule, XnActualPropertiesHash, strModuleName); + + nRetVal = XnPropertySetDataAttachModule(pSet->pData, strModuleName, pModule); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pModule); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetRemoveModule(XnPropertySet* pSet, const XnChar* strModuleName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + + XnActualPropertiesHash* pModule = NULL; + nRetVal = XnPropertySetDataDetachModule(pSet->pData, strModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // now free its memory + XN_DELETE(pModule); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetAddIntProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(strProperty); + + // get module + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + // add property + nRetVal = pModule->Add(strProperty, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetAddRealProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(strProperty); + + // get module + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + // add property + nRetVal = pModule->Add(strProperty, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetAddStringProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(strProperty); + XN_VALIDATE_INPUT_PTR(strValue); + + // get module + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + // add property + nRetVal = pModule->Add(strProperty, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetAddGeneralProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty, const XnGeneralBuffer* pgbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(strProperty); + XN_VALIDATE_INPUT_PTR(pgbValue); + + // get module + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + // add property + nRetVal = pModule->Add(strProperty, *pgbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetRemoveProperty(XnPropertySet* pSet, const XnChar* strModuleName, const XnChar* strProperty) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(strProperty); + + // get module + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + // remove the property + XnProperty* pProp; + nRetVal = pModule->Remove(strProperty); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetGetModuleEnumerator(const XnPropertySet* pSet, XnPropertySetModuleEnumerator** ppEnumerator) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_OUTPUT_PTR(ppEnumerator); + + XnPropertySetModuleEnumerator* pEnumer; + XN_VALIDATE_ALLOC(pEnumer, XnPropertySetModuleEnumerator); + + pEnumer->bFirst = TRUE; + pEnumer->it = pSet->pData->end(); + pEnumer->pModules = pSet->pData; + + *ppEnumerator = pEnumer; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorFree(XnPropertySetModuleEnumerator** ppEnumer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(ppEnumer); + XN_VALIDATE_INPUT_PTR(*ppEnumer); + + xnOSFree(*ppEnumer); + *ppEnumer = NULL; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorMoveNext(XnPropertySetModuleEnumerator* pEnumerator, XnBool* pbEnd) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pbEnd); + + if (pEnumerator->bFirst) + { + pEnumerator->it = pEnumerator->pModules->begin(); + pEnumerator->bFirst = FALSE; + } + else if (pEnumerator->it == pEnumerator->pModules->end()) + { + return XN_STATUS_ILLEGAL_POSITION; + } + else + { + pEnumerator->it++; + } + + *pbEnd = (pEnumerator->it == pEnumerator->pModules->end()); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetModuleEnumeratorGetCurrent(const XnPropertySetModuleEnumerator* pEnumer, const XnChar** pstrModuleName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumer); + XN_VALIDATE_OUTPUT_PTR(pstrModuleName); + + if (pEnumer->it == pEnumer->pModules->end()) + { + return XN_STATUS_ILLEGAL_POSITION; + } + + *pstrModuleName = pEnumer->it.Key(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetGetEnumerator(const XnPropertySet* pSet, XnPropertySetEnumerator** ppEnumerator, const XnChar* strModule /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_OUTPUT_PTR(ppEnumerator); + + if (strModule != NULL) + { + // make sure module exists + XnPropertySetData::ConstIterator it = pSet->pData->end(); + nRetVal = pSet->pData->Find(strModule, it); + XN_IS_STATUS_OK(nRetVal); + } + + XnPropertySetEnumerator* pEnumer; + XN_VALIDATE_ALLOC(pEnumer, XnPropertySetEnumerator); + + pEnumer->bFirst = TRUE; + pEnumer->pModules = pSet->pData; + if (strModule != NULL) + { + strncpy(pEnumer->strModule, strModule, XN_DEVICE_MAX_STRING_LENGTH); + } + else + { + pEnumer->strModule[0] = '\0'; + } + + *ppEnumerator = pEnumer; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetFindProperty(const XnPropertySet* pSet, const XnChar* strModule, const XnChar* strProp, XnPropertySetEnumerator** ppEnumerator) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSet); + XN_VALIDATE_INPUT_PTR(strModule); + XN_VALIDATE_INPUT_PTR(strProp); + XN_VALIDATE_OUTPUT_PTR(ppEnumerator); + + // find module + XnPropertySetData::Iterator itModule = pSet->pData->end(); + nRetVal = pSet->pData->Find(strModule, itModule); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pModule = itModule.Value(); + + // find property + XnActualPropertiesHash::Iterator itProp = pModule->end(); + nRetVal = pModule->Find(strProp, itProp); + XN_IS_STATUS_OK(nRetVal); + + // create enumerator + XnPropertySetEnumerator* pEnumer; + XN_VALIDATE_ALLOC(pEnumer, XnPropertySetEnumerator); + + pEnumer->itModule = itModule; + pEnumer->itProp = itProp; + pEnumer->pModules = pSet->pData; + pEnumer->strModule[0] = '\0'; + pEnumer->bFirst = FALSE; + + *ppEnumerator = pEnumer; + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorFree(XnPropertySetEnumerator** ppEnumerator) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(ppEnumerator); + XN_VALIDATE_INPUT_PTR(*ppEnumerator); + + xnOSFree(*ppEnumerator); + *ppEnumerator = NULL; + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorMoveNext(XnPropertySetEnumerator* pEnumerator, XnBool* pbEnd) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pbEnd); + + *pbEnd = TRUE; + + if (pEnumerator->strModule[0] != '\0') // single module + { + if (pEnumerator->bFirst) + { + pEnumerator->bFirst = FALSE; + + // find this module + nRetVal = pEnumerator->pModules->Find(pEnumerator->strModule, pEnumerator->itModule); + if (nRetVal == XN_STATUS_NO_MATCH) + { + pEnumerator->itModule = pEnumerator->pModules->end(); + } + XN_IS_STATUS_OK(nRetVal); + + pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); + } + else if (pEnumerator->itProp == pEnumerator->itModule.Value()->end()) + { + return XN_STATUS_ILLEGAL_POSITION; + } + else + { + // advance prop iterator + pEnumerator->itProp++; + } + + *pbEnd = (pEnumerator->itProp == pEnumerator->itModule.Value()->end()); + } + else // all modules + { + if (pEnumerator->bFirst) + { + pEnumerator->bFirst = FALSE; + + // search for the first modules that has properties + pEnumerator->itModule = pEnumerator->pModules->begin(); + while (pEnumerator->itModule != pEnumerator->pModules->end() && pEnumerator->itModule.Value()->IsEmpty()) + { + pEnumerator->itModule++; + } + + // if we found one, take it's first property + if (pEnumerator->itModule != pEnumerator->pModules->end()) + { + pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); + *pbEnd = FALSE; + } + else + { + *pbEnd = TRUE; + } + } + else if (pEnumerator->itModule == pEnumerator->pModules->end()) + { + return XN_STATUS_ILLEGAL_POSITION; + } + else + { + // move to next one + pEnumerator->itProp++; + + // check if we reached end of module + if (pEnumerator->itProp == pEnumerator->itModule.Value()->end()) + { + // move to next module with properties + do + { + pEnumerator->itModule++; + } + while (pEnumerator->itModule != pEnumerator->pModules->end() && pEnumerator->itModule.Value()->IsEmpty()); + + // if we found one, take it's first property + if (pEnumerator->itModule != pEnumerator->pModules->end()) + { + pEnumerator->itProp = pEnumerator->itModule.Value()->begin(); + *pbEnd = FALSE; + } + else + { + *pbEnd = TRUE; + } + } + else + { + *pbEnd = FALSE; + } + } + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorGetCurrentPropertyInfo(const XnPropertySetEnumerator* pEnumerator, XnPropertyType* pnType, const XnChar** pstrModule, const XnChar** pstrProp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pnType); + XN_VALIDATE_OUTPUT_PTR(pstrModule); + XN_VALIDATE_OUTPUT_PTR(pstrProp); + + XnProperty* pProp = pEnumerator->itProp.Value(); + *pnType = pProp->GetType(); + *pstrModule = pProp->GetModule(); + *pstrProp = pProp->GetName(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorGetIntValue(const XnPropertySetEnumerator* pEnumerator, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pnValue); + + XnProperty* pPropBase = pEnumerator->itProp.Value(); + if (pPropBase->GetType() != XN_PROPERTY_TYPE_INTEGER) + { + return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; + } + + XnActualIntProperty* pProp = (XnActualIntProperty*)pPropBase; + *pnValue = pProp->GetValue(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorGetRealValue(const XnPropertySetEnumerator* pEnumerator, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pdValue); + + XnProperty* pPropBase = pEnumerator->itProp.Value(); + if (pPropBase->GetType() != XN_PROPERTY_TYPE_REAL) + { + return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; + } + + XnActualRealProperty* pProp = (XnActualRealProperty*)pPropBase; + *pdValue = pProp->GetValue(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorGetStringValue(const XnPropertySetEnumerator* pEnumerator, const XnChar** pstrValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pstrValue); + + XnProperty* pPropBase = pEnumerator->itProp.Value(); + if (pPropBase->GetType() != XN_PROPERTY_TYPE_STRING) + { + return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; + } + + XnActualStringProperty* pProp = (XnActualStringProperty*)pPropBase; + *pstrValue = pProp->GetValue(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetEnumeratorGetGeneralValue(const XnPropertySetEnumerator* pEnumerator, XnGeneralBuffer* pgbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pEnumerator); + XN_VALIDATE_OUTPUT_PTR(pgbValue); + + XnProperty* pPropBase = pEnumerator->itProp.Value(); + if (pPropBase->GetType() != XN_PROPERTY_TYPE_GENERAL) + { + return XN_STATUS_DEVICE_PROPERTY_BAD_TYPE; + } + + XnActualGeneralProperty* pProp = (XnActualGeneralProperty*)pPropBase; + *pgbValue = pProp->GetValue(); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetDataAttachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash* pModule) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSetData); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_INPUT_PTR(pModule); + + nRetVal = pSetData->Set(strModuleName, pModule); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetDataDetachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash** ppModule) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pSetData); + XN_VALIDATE_INPUT_PTR(strModuleName); + XN_VALIDATE_OUTPUT_PTR(ppModule); + + // remove it + nRetVal = pSetData->Remove(strModuleName, *ppModule); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnPropertySetCloneModule(const XnPropertySet* pSource, XnPropertySet* pDest, const XnChar* strModule, const XnChar* strNewName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnActualPropertiesHash* pModuleProps; + nRetVal = pSource->pData->Get(strModule, pModuleProps); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddModule(pDest, strNewName); + XN_IS_STATUS_OK(nRetVal); + + for (XnActualPropertiesHash::ConstIterator it = pModuleProps->begin(); it != pModuleProps->end(); ++it) + { + XnProperty* pProp = it.Value(); + switch (pProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; + nRetVal = XnPropertySetAddIntProperty(pDest, strNewName, pIntProp->GetName(), pIntProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; + nRetVal = XnPropertySetAddRealProperty(pDest, strNewName, pRealProp->GetName(), pRealProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; + nRetVal = XnPropertySetAddStringProperty(pDest, strNewName, pStrProp->GetName(), pStrProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; + nRetVal = XnPropertySetAddGeneralProperty(pDest, strNewName, pGenProp->GetName(), &pGenProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Unknown property type: %d", pProp->GetType()); + } + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnPropertySetInternal.h b/Source/XnDDK/XnPropertySetInternal.h index 2f3b287..80335d0 100644 --- a/Source/XnDDK/XnPropertySetInternal.h +++ b/Source/XnDDK/XnPropertySetInternal.h @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_PROPERTY_SET_INTERNAL_H__ -#define __XN_PROPERTY_SET_INTERNAL_H__ - -#include -#include "XnActualPropertiesHash.h" - -XN_DECLARE_STRINGS_HASH_DECL(XN_DDK_CPP_API, XnActualPropertiesHash*, XnPropertySetDataInternal) - -class XnPropertySetData; - -struct XnPropertySet -{ - XnPropertySetData* pData; -}; - -class XnPropertySetData : public XnPropertySetDataInternal -{ -public: - ~XnPropertySetData() - { - XnPropertySet set; - set.pData = this; - XnPropertySetClear(&set); - } -}; - -#define _XN_PROPERTY_SET_NAME(name) __ ## name ## _ ## Data - -#define XN_PROPERTY_SET_CREATE_ON_STACK(name) \ - XnPropertySetData _XN_PROPERTY_SET_NAME(name); \ - XnPropertySet name; \ - name.pData = &_XN_PROPERTY_SET_NAME(name); - -XN_DDK_API XnStatus XnPropertySetDataAttachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash* pModule); -XN_DDK_API XnStatus XnPropertySetDataDetachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash** ppModule); -XN_DDK_API XnStatus XnPropertySetCloneModule(XnPropertySet* pSource, XnPropertySet* pDest, const XnChar* strModule, const XnChar* strNewName); - -#endif //__XN_PROPERTY_SET_INTERNAL_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_PROPERTY_SET_INTERNAL_H__ +#define __XN_PROPERTY_SET_INTERNAL_H__ + +#include +#include "XnActualPropertiesHash.h" + +XN_DECLARE_STRINGS_HASH_DECL(XN_DDK_CPP_API, XnActualPropertiesHash*, XnPropertySetDataInternal) + +class XnPropertySetData; + +struct XnPropertySet +{ + XnPropertySetData* pData; +}; + +class XnPropertySetData : public XnPropertySetDataInternal +{ +public: + ~XnPropertySetData() + { + XnPropertySet set; + set.pData = this; + XnPropertySetClear(&set); + } +}; + +#define _XN_PROPERTY_SET_NAME(name) __ ## name ## _ ## Data + +#define XN_PROPERTY_SET_CREATE_ON_STACK(name) \ + XnPropertySetData _XN_PROPERTY_SET_NAME(name); \ + XnPropertySet name; \ + name.pData = &_XN_PROPERTY_SET_NAME(name); + +XN_DDK_API XnStatus XnPropertySetDataAttachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash* pModule); +XN_DDK_API XnStatus XnPropertySetDataDetachModule(XnPropertySetData* pSetData, const XnChar* strModuleName, XnActualPropertiesHash** ppModule); +XN_DDK_API XnStatus XnPropertySetCloneModule(const XnPropertySet* pSource, XnPropertySet* pDest, const XnChar* strModule, const XnChar* strNewName); + +#endif //__XN_PROPERTY_SET_INTERNAL_H__ diff --git a/Source/XnDDK/XnRealProperty.cpp b/Source/XnDDK/XnRealProperty.cpp index 5980939..a76f8c5 100644 --- a/Source/XnDDK/XnRealProperty.cpp +++ b/Source/XnDDK/XnRealProperty.cpp @@ -1,100 +1,100 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnRealProperty.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnRealProperty::XnRealProperty(const XnChar* strName, XnDouble* pValueHolder, const XnChar* strModule /* = "" */) : - XnProperty(XN_PROPERTY_TYPE_REAL, pValueHolder, strName, strModule) -{ -} - -XnStatus XnRealProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDouble dValue; - - nRetVal = xnOSReadDoubleFromINI(csINIFile, csSection, GetName(), &dValue); - if (nRetVal == XN_STATUS_OK) - { - nRetVal = SetValue(dValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnRealProperty::CopyValueImpl(void* pDest, const void* pSource) const -{ - (*(XnDouble*)pDest) = (*(const XnDouble*)pSource); - return XN_STATUS_OK; -} - -XnBool XnRealProperty::IsEqual(const void* pValue1, const void* pValue2) const -{ - return (*(XnDouble*)pValue1) == (*(XnDouble*)pValue2); -} - -XnStatus XnRealProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) -{ - SetFuncPtr pCallback = (SetFuncPtr)pFunc; - return pCallback(this, *(const XnDouble*)pValue, pCookie); -} - -XnStatus XnRealProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const -{ - GetFuncPtr pCallback = (GetFuncPtr)pFunc; - return pCallback(this, (XnDouble*)pValue, pCookie); -} - -XnBool XnRealProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const -{ - sprintf(csValue, "%f", *(XnDouble*)pValue); - return TRUE; -} - -XnStatus XnRealProperty::AddToPropertySet(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDouble dValue; - nRetVal = GetValue(&dValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddRealProperty(pSet, GetModule(), GetName(), dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnRealProperty.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnRealProperty::XnRealProperty(const XnChar* strName, XnDouble* pValueHolder, const XnChar* strModule /* = "" */) : + XnProperty(XN_PROPERTY_TYPE_REAL, pValueHolder, strName, strModule) +{ +} + +XnStatus XnRealProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDouble dValue; + + nRetVal = xnOSReadDoubleFromINI(csINIFile, csSection, GetName(), &dValue); + if (nRetVal == XN_STATUS_OK) + { + nRetVal = SetValue(dValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnRealProperty::CopyValueImpl(void* pDest, const void* pSource) const +{ + (*(XnDouble*)pDest) = (*(const XnDouble*)pSource); + return XN_STATUS_OK; +} + +XnBool XnRealProperty::IsEqual(const void* pValue1, const void* pValue2) const +{ + return (*(XnDouble*)pValue1) == (*(XnDouble*)pValue2); +} + +XnStatus XnRealProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) +{ + SetFuncPtr pCallback = (SetFuncPtr)pFunc; + return pCallback(this, *(const XnDouble*)pValue, pCookie); +} + +XnStatus XnRealProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const +{ + GetFuncPtr pCallback = (GetFuncPtr)pFunc; + return pCallback(this, (XnDouble*)pValue, pCookie); +} + +XnBool XnRealProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const +{ + sprintf(csValue, "%f", *(XnDouble*)pValue); + return TRUE; +} + +XnStatus XnRealProperty::AddToPropertySet(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDouble dValue; + nRetVal = GetValue(&dValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddRealProperty(pSet, GetModule(), GetName(), dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnRealProperty.h b/Source/XnDDK/XnRealProperty.h index 2af3c24..549f48d 100644 --- a/Source/XnDDK/XnRealProperty.h +++ b/Source/XnDDK/XnRealProperty.h @@ -1,91 +1,91 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_REAL_PROPERTY_H__ -#define __XN_REAL_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type integer. -*/ -class XN_DDK_CPP_API XnRealProperty : public XnProperty -{ -public: - XnRealProperty(const XnChar* strName, XnDouble* pValueHolder, const XnChar* strModule = ""); - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnRealProperty* pSender, XnDouble dValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnRealProperty* pSender, XnDouble* pdValue, void* pCookie); - - inline XnStatus SetValue(XnDouble dValue) - { - return XnProperty::SetValue(&dValue); - } - - inline XnStatus GetValue(XnDouble* pdValue) const - { - XN_VALIDATE_OUTPUT_PTR(pdValue); - return XnProperty::GetValue(pdValue); - } - - inline XnStatus UnsafeUpdateValue(XnDouble dValue) - { - return XnProperty::UnsafeUpdateValue(&dValue); - } - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); - } - - virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); - - XnStatus AddToPropertySet(XnPropertySet* pSet); - -protected: - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; - virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; - virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); - virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; - virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; -}; - -#endif //__XN_REAL_PROPERTY_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_REAL_PROPERTY_H__ +#define __XN_REAL_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type integer. +*/ +class XN_DDK_CPP_API XnRealProperty : public XnProperty +{ +public: + XnRealProperty(const XnChar* strName, XnDouble* pValueHolder, const XnChar* strModule = ""); + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnRealProperty* pSender, XnDouble dValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnRealProperty* pSender, XnDouble* pdValue, void* pCookie); + + inline XnStatus SetValue(XnDouble dValue) + { + return XnProperty::SetValue(&dValue); + } + + inline XnStatus GetValue(XnDouble* pdValue) const + { + XN_VALIDATE_OUTPUT_PTR(pdValue); + return XnProperty::GetValue(pdValue); + } + + inline XnStatus UnsafeUpdateValue(XnDouble dValue) + { + return XnProperty::UnsafeUpdateValue(&dValue); + } + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); + } + + virtual XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); + + XnStatus AddToPropertySet(XnPropertySet* pSet); + +protected: + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; + virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; + virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); + virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; + virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; +}; + +#endif //__XN_REAL_PROPERTY_H__ diff --git a/Source/XnDDK/XnShiftToDepth.cpp b/Source/XnDDK/XnShiftToDepth.cpp index 47a0394..54b7a20 100644 --- a/Source/XnDDK/XnShiftToDepth.cpp +++ b/Source/XnDDK/XnShiftToDepth.cpp @@ -1,150 +1,150 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnShiftToDepth.h" -#include -#include "XnDDK.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnShiftToDepthInit(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig) -{ - XN_VALIDATE_INPUT_PTR(pShiftToDepth); - XN_VALIDATE_INPUT_PTR(pConfig); - - XN_VALIDATE_ALIGNED_CALLOC(pShiftToDepth->pShiftToDepthTable, XnDepthPixel, pConfig->nDeviceMaxShiftValue+1, XN_DEFAULT_MEM_ALIGN); - XN_VALIDATE_ALIGNED_CALLOC(pShiftToDepth->pDepthToShiftTable, XnUInt16, pConfig->nDeviceMaxDepthValue+1, XN_DEFAULT_MEM_ALIGN); - pShiftToDepth->bIsInitialized = TRUE; - - // store allocation sizes - pShiftToDepth->nShiftsCount = pConfig->nDeviceMaxShiftValue + 1; - pShiftToDepth->nDepthsCount = pConfig->nDeviceMaxDepthValue + 1; - - return XnShiftToDepthUpdate(pShiftToDepth, pConfig); -} - -XN_DDK_API XnStatus XnShiftToDepthUpdate(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig) -{ - XN_VALIDATE_INPUT_PTR(pShiftToDepth); - XN_VALIDATE_INPUT_PTR(pConfig); - - // check max shift wasn't changed (if so, memory should be re-allocated) - if (pConfig->nDeviceMaxShiftValue > pShiftToDepth->nShiftsCount) - return XN_STATUS_DEVICE_INVALID_MAX_SHIFT; - - // check max depth wasn't changed (if so, memory should be re-allocated) - if (pConfig->nDeviceMaxDepthValue > pShiftToDepth->nDepthsCount) - return XN_STATUS_DEVICE_INVALID_MAX_DEPTH; - - XnUInt32 nIndex = 0; - XnInt16 nShiftValue = 0; - XnDouble dFixedRefX = 0; - XnDouble dMetric = 0; - XnDouble dDepth = 0; - XnDouble dPlanePixelSize = pConfig->fZeroPlanePixelSize; - XnDouble dPlaneDsr = pConfig->nZeroPlaneDistance; - XnDouble dPlaneDcl = pConfig->fEmitterDCmosDistance; - XnInt32 nConstShift = pConfig->nParamCoeff * pConfig->nConstShift; - - dPlanePixelSize *= pConfig->nPixelSizeFactor; - nConstShift /= pConfig->nPixelSizeFactor; - - XnDepthPixel* pShiftToDepthTable = pShiftToDepth->pShiftToDepthTable; - XnUInt16* pDepthToShiftTable = pShiftToDepth->pDepthToShiftTable; - - xnOSMemSet(pShiftToDepthTable, 0, pShiftToDepth->nShiftsCount * sizeof(XnDepthPixel)); - xnOSMemSet(pDepthToShiftTable, 0, pShiftToDepth->nDepthsCount * sizeof(XnUInt16)); - - XnUInt16 nLastDepth = 0; - XnUInt16 nLastIndex = 0; - - for (nIndex = 1; nIndex < pConfig->nDeviceMaxShiftValue; nIndex++) - { - nShiftValue = nIndex; - - dFixedRefX = (XnDouble)(nShiftValue - nConstShift) / (XnDouble)pConfig->nParamCoeff; - dFixedRefX -= 0.375; - dMetric = dFixedRefX * dPlanePixelSize; - dDepth = pConfig->nShiftScale * ((dMetric * dPlaneDsr / (dPlaneDcl - dMetric)) + dPlaneDsr); - - // check cut-offs - if ((dDepth > pConfig->nDepthMinCutOff) && (dDepth < pConfig->nDepthMaxCutOff)) - { - pShiftToDepthTable[nIndex] = (XnUInt16)dDepth; - - for (XnUInt16 i = nLastDepth; i < dDepth; i++) - pDepthToShiftTable[i] = nLastIndex; - - nLastIndex = nIndex; - nLastDepth = (XnUInt16)dDepth; - } - } - - for (XnUInt16 i = nLastDepth; i <= pConfig->nDeviceMaxDepthValue; i++) - pDepthToShiftTable[i] = nLastIndex; - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnShiftToDepthConvert(XnShiftToDepthTables* pShiftToDepth, XnUInt16* pInput, XnUInt32 nInputSize, XnDepthPixel* pOutput) -{ - XN_VALIDATE_INPUT_PTR(pShiftToDepth); - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - - XnUInt16* pInputEnd = pInput + nInputSize; - XnDepthPixel* pShiftToDepthTable = pShiftToDepth->pShiftToDepthTable; - - while (pInput != pInputEnd) - { - pOutput[0] = pShiftToDepthTable[pInput[0]]; - - pInput++; - pOutput++; - } - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnShiftToDepthFree(XnShiftToDepthTables* pShiftToDepth) -{ - XN_VALIDATE_INPUT_PTR(pShiftToDepth); - - if (pShiftToDepth->bIsInitialized) - { - XN_ALIGNED_FREE_AND_NULL(pShiftToDepth->pDepthToShiftTable); - XN_ALIGNED_FREE_AND_NULL(pShiftToDepth->pShiftToDepthTable); - pShiftToDepth->bIsInitialized = FALSE; - } - - return XN_STATUS_OK; -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnShiftToDepth.h" +#include +#include "XnDDK.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnShiftToDepthInit(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig) +{ + XN_VALIDATE_INPUT_PTR(pShiftToDepth); + XN_VALIDATE_INPUT_PTR(pConfig); + + XN_VALIDATE_ALIGNED_CALLOC(pShiftToDepth->pShiftToDepthTable, XnDepthPixel, pConfig->nDeviceMaxShiftValue+1, XN_DEFAULT_MEM_ALIGN); + XN_VALIDATE_ALIGNED_CALLOC(pShiftToDepth->pDepthToShiftTable, XnUInt16, pConfig->nDeviceMaxDepthValue+1, XN_DEFAULT_MEM_ALIGN); + pShiftToDepth->bIsInitialized = TRUE; + + // store allocation sizes + pShiftToDepth->nShiftsCount = pConfig->nDeviceMaxShiftValue + 1; + pShiftToDepth->nDepthsCount = pConfig->nDeviceMaxDepthValue + 1; + + return XnShiftToDepthUpdate(pShiftToDepth, pConfig); +} + +XN_DDK_API XnStatus XnShiftToDepthUpdate(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig) +{ + XN_VALIDATE_INPUT_PTR(pShiftToDepth); + XN_VALIDATE_INPUT_PTR(pConfig); + + // check max shift wasn't changed (if so, memory should be re-allocated) + if (pConfig->nDeviceMaxShiftValue > pShiftToDepth->nShiftsCount) + return XN_STATUS_DEVICE_INVALID_MAX_SHIFT; + + // check max depth wasn't changed (if so, memory should be re-allocated) + if (pConfig->nDeviceMaxDepthValue > pShiftToDepth->nDepthsCount) + return XN_STATUS_DEVICE_INVALID_MAX_DEPTH; + + XnUInt32 nIndex = 0; + XnInt16 nShiftValue = 0; + XnDouble dFixedRefX = 0; + XnDouble dMetric = 0; + XnDouble dDepth = 0; + XnDouble dPlanePixelSize = pConfig->fZeroPlanePixelSize; + XnDouble dPlaneDsr = pConfig->nZeroPlaneDistance; + XnDouble dPlaneDcl = pConfig->fEmitterDCmosDistance; + XnInt32 nConstShift = pConfig->nParamCoeff * pConfig->nConstShift; + + dPlanePixelSize *= pConfig->nPixelSizeFactor; + nConstShift /= pConfig->nPixelSizeFactor; + + XnDepthPixel* pShiftToDepthTable = pShiftToDepth->pShiftToDepthTable; + XnUInt16* pDepthToShiftTable = pShiftToDepth->pDepthToShiftTable; + + xnOSMemSet(pShiftToDepthTable, 0, pShiftToDepth->nShiftsCount * sizeof(XnDepthPixel)); + xnOSMemSet(pDepthToShiftTable, 0, pShiftToDepth->nDepthsCount * sizeof(XnUInt16)); + + XnUInt16 nLastDepth = 0; + XnUInt16 nLastIndex = 0; + + for (nIndex = 1; nIndex < pConfig->nDeviceMaxShiftValue; nIndex++) + { + nShiftValue = nIndex; + + dFixedRefX = (XnDouble)(nShiftValue - nConstShift) / (XnDouble)pConfig->nParamCoeff; + dFixedRefX -= 0.375; + dMetric = dFixedRefX * dPlanePixelSize; + dDepth = pConfig->nShiftScale * ((dMetric * dPlaneDsr / (dPlaneDcl - dMetric)) + dPlaneDsr); + + // check cut-offs + if ((dDepth > pConfig->nDepthMinCutOff) && (dDepth < pConfig->nDepthMaxCutOff)) + { + pShiftToDepthTable[nIndex] = (XnUInt16)dDepth; + + for (XnUInt16 i = nLastDepth; i < dDepth; i++) + pDepthToShiftTable[i] = nLastIndex; + + nLastIndex = nIndex; + nLastDepth = (XnUInt16)dDepth; + } + } + + for (XnUInt16 i = nLastDepth; i <= pConfig->nDeviceMaxDepthValue; i++) + pDepthToShiftTable[i] = nLastIndex; + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnShiftToDepthConvert(XnShiftToDepthTables* pShiftToDepth, XnUInt16* pInput, XnUInt32 nInputSize, XnDepthPixel* pOutput) +{ + XN_VALIDATE_INPUT_PTR(pShiftToDepth); + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + + XnUInt16* pInputEnd = pInput + nInputSize; + XnDepthPixel* pShiftToDepthTable = pShiftToDepth->pShiftToDepthTable; + + while (pInput != pInputEnd) + { + pOutput[0] = pShiftToDepthTable[pInput[0]]; + + pInput++; + pOutput++; + } + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnShiftToDepthFree(XnShiftToDepthTables* pShiftToDepth) +{ + XN_VALIDATE_INPUT_PTR(pShiftToDepth); + + if (pShiftToDepth->bIsInitialized) + { + XN_ALIGNED_FREE_AND_NULL(pShiftToDepth->pDepthToShiftTable); + XN_ALIGNED_FREE_AND_NULL(pShiftToDepth->pShiftToDepthTable); + pShiftToDepth->bIsInitialized = FALSE; + } + + return XN_STATUS_OK; +} + diff --git a/Source/XnDDK/XnShiftToDepth.h b/Source/XnDDK/XnShiftToDepth.h index cdfca90..b1bd6c3 100644 --- a/Source/XnDDK/XnShiftToDepth.h +++ b/Source/XnDDK/XnShiftToDepth.h @@ -1,85 +1,85 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_SHIFT_TO_DEPTH_H_ -#define _XN_SHIFT_TO_DEPTH_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnShiftToDepthConfig -{ - /** The zero plane distance in depth units. */ - XnDepthPixel nZeroPlaneDistance; - /** The zero plane pixel size */ - XnFloat fZeroPlanePixelSize; - /** The distance between the emitter and the Depth Cmos */ - XnFloat fEmitterDCmosDistance; - /** The maximum possible shift value from this device. */ - XnUInt32 nDeviceMaxShiftValue; - /** The maximum possible depth from this device (as opposed to a cut-off). */ - XnUInt32 nDeviceMaxDepthValue; - - XnUInt32 nConstShift; - XnUInt32 nPixelSizeFactor; - XnUInt32 nParamCoeff; - XnUInt32 nShiftScale; - - XnDepthPixel nDepthMinCutOff; - XnDepthPixel nDepthMaxCutOff; - -} XnShiftToDepthConfig; - -typedef struct XnShiftToDepthTables -{ - XnBool bIsInitialized; - /** The shift-to-depth table. */ - XnDepthPixel* pShiftToDepthTable; - /** The number of entries in the shift-to-depth table. */ - XnUInt32 nShiftsCount; - /** The depth-to-shift table. */ - XnUInt16* pDepthToShiftTable; - /** The number of entries in the depth-to-shift table. */ - XnUInt32 nDepthsCount; -} XnShiftToDepthTables; - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnShiftToDepthInit(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig); -XN_DDK_API XnStatus XnShiftToDepthUpdate(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig); -XN_DDK_API XnStatus XnShiftToDepthConvert(XnShiftToDepthTables* pShiftToDepth, XnUInt16* pInput, XnUInt32 nInputSize, XnDepthPixel* pOutput); -XN_DDK_API XnStatus XnShiftToDepthFree(XnShiftToDepthTables* pShiftToDepth); - -#endif //_XN_SHIFT_TO_DEPTH_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_SHIFT_TO_DEPTH_H_ +#define _XN_SHIFT_TO_DEPTH_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnShiftToDepthConfig +{ + /** The zero plane distance in depth units. */ + XnDepthPixel nZeroPlaneDistance; + /** The zero plane pixel size */ + XnFloat fZeroPlanePixelSize; + /** The distance between the emitter and the Depth Cmos */ + XnFloat fEmitterDCmosDistance; + /** The maximum possible shift value from this device. */ + XnUInt32 nDeviceMaxShiftValue; + /** The maximum possible depth from this device (as opposed to a cut-off). */ + XnUInt32 nDeviceMaxDepthValue; + + XnUInt32 nConstShift; + XnUInt32 nPixelSizeFactor; + XnUInt32 nParamCoeff; + XnUInt32 nShiftScale; + + XnDepthPixel nDepthMinCutOff; + XnDepthPixel nDepthMaxCutOff; + +} XnShiftToDepthConfig; + +typedef struct XnShiftToDepthTables +{ + XnBool bIsInitialized; + /** The shift-to-depth table. */ + XnDepthPixel* pShiftToDepthTable; + /** The number of entries in the shift-to-depth table. */ + XnUInt32 nShiftsCount; + /** The depth-to-shift table. */ + XnUInt16* pDepthToShiftTable; + /** The number of entries in the depth-to-shift table. */ + XnUInt32 nDepthsCount; +} XnShiftToDepthTables; + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnShiftToDepthInit(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig); +XN_DDK_API XnStatus XnShiftToDepthUpdate(XnShiftToDepthTables* pShiftToDepth, const XnShiftToDepthConfig* pConfig); +XN_DDK_API XnStatus XnShiftToDepthConvert(XnShiftToDepthTables* pShiftToDepth, XnUInt16* pInput, XnUInt32 nInputSize, XnDepthPixel* pOutput); +XN_DDK_API XnStatus XnShiftToDepthFree(XnShiftToDepthTables* pShiftToDepth); + +#endif //_XN_SHIFT_TO_DEPTH_H_ diff --git a/Source/XnDDK/XnShiftToDepthStreamHelper.cpp b/Source/XnDDK/XnShiftToDepthStreamHelper.cpp index 27c6e2b..13a7ede 100644 --- a/Source/XnDDK/XnShiftToDepthStreamHelper.cpp +++ b/Source/XnDDK/XnShiftToDepthStreamHelper.cpp @@ -1,299 +1,299 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#include "XnShiftToDepthStreamHelper.h" - -XnShiftToDepthStreamHelper::XnShiftToDepthStreamHelper(XnDeviceModule* pModule) : - m_ShiftToDepthTable(XN_STREAM_PROPERTY_S2D_TABLE, NULL, 0, NULL), - m_DepthToShiftTable(XN_STREAM_PROPERTY_D2S_TABLE, NULL, 0, NULL), - m_pModule(pModule), - m_bPropertiesAdded(FALSE) -{ - m_ShiftToDepthTable.UpdateGetCallback(GetShiftToDepthTableCallback, this); - m_DepthToShiftTable.UpdateGetCallback(GetDepthToShiftTableCallback, this); - xnOSMemSet(&m_ShiftToDepthTables, 0, sizeof(XnShiftToDepthTables)); -} - -XnShiftToDepthStreamHelper::~XnShiftToDepthStreamHelper() -{ - XnShiftToDepthStreamHelper::Free(); -} - -XnStatus XnShiftToDepthStreamHelper::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // old depth streams did not have S2D tables as actual properties. Add these properties - XnBool bDoesExist = FALSE; - nRetVal = m_pModule->DoesPropertyExist(XN_STREAM_PROPERTY_S2D_TABLE, &bDoesExist); - XN_IS_STATUS_OK(nRetVal); - - if (!bDoesExist) - { - // add properties to the module - XN_VALIDATE_ADD_PROPERTIES(m_pModule, &m_ShiftToDepthTable, &m_DepthToShiftTable); - - m_bPropertiesAdded = TRUE; - - // now create tables and register to properties - nRetVal = InitShiftToDepth(); - XN_IS_STATUS_OK(nRetVal); - } - else - { - m_ShiftToDepthTables.pShiftToDepthTable = (XnDepthPixel*)m_ShiftToDepthTable.GetValue().pData; - m_ShiftToDepthTables.pDepthToShiftTable = (XnUInt16*)m_DepthToShiftTable.GetValue().pData; - } - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::Free() -{ - XnShiftToDepthFree(&m_ShiftToDepthTables); - return XN_STATUS_OK; -} - -XnStatus XnShiftToDepthStreamHelper::InitShiftToDepth() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // register to any shift-to-depth property (so tables can be updated if needed) - const XnChar* propNames[] = - { - XN_STREAM_PROPERTY_MIN_DEPTH, - XN_STREAM_PROPERTY_MAX_DEPTH, - XN_STREAM_PROPERTY_CONST_SHIFT, - XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, - XN_STREAM_PROPERTY_PARAM_COEFF, - XN_STREAM_PROPERTY_SHIFT_SCALE, - XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, - XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, - XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE - }; - - XnUInt32 nPropCount = sizeof(propNames) / sizeof(const XnChar*); - - XnProperty* pProperty = NULL; - for (XnUInt32 i = 0; i < nPropCount; ++i) - { - nRetVal = m_pModule->GetProperty(propNames[i], &pProperty); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProperty->OnChangeEvent().Register(ShiftToDepthPropertyValueChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - } - - // register for tables size properties - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_SHIFT, &pProperty); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProperty->OnChangeEvent().Register(DeviceS2DTablesSizeChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &pProperty); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProperty->OnChangeEvent().Register(DeviceS2DTablesSizeChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - - // now init the tables - XnShiftToDepthConfig Config; - nRetVal = GetShiftToDepthConfig(Config); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnShiftToDepthInit(&m_ShiftToDepthTables, &Config); - XN_IS_STATUS_OK(nRetVal); - - // replace tables buffers - m_ShiftToDepthTable.ReplaceBuffer(m_ShiftToDepthTables.pShiftToDepthTable, m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel)); - m_DepthToShiftTable.ReplaceBuffer(m_ShiftToDepthTables.pDepthToShiftTable, m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16)); - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::GetShiftToDepthConfig(XnShiftToDepthConfig& Config) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nTemp; - XnDouble dTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nZeroPlaneDistance = (XnUInt16)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &dTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.fZeroPlanePixelSize = (XnFloat)dTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, &dTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.fEmitterDCmosDistance = (XnFloat)dTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_SHIFT, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nDeviceMaxShiftValue = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nDeviceMaxDepthValue = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_CONST_SHIFT, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nConstShift = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nPixelSizeFactor = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_PARAM_COEFF, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nParamCoeff = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nShiftScale = (XnUInt32)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MIN_DEPTH, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nDepthMinCutOff = (XnDepthPixel)nTemp; - - nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_DEPTH, &nTemp); - XN_IS_STATUS_OK(nRetVal); - - Config.nDepthMaxCutOff = (XnDepthPixel)nTemp; - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::RaiseChangeEvents() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_ShiftToDepthTable.UnsafeUpdateValue(XnGeneralBufferPack(m_ShiftToDepthTables.pShiftToDepthTable, m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel))); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_DepthToShiftTable.UnsafeUpdateValue(XnGeneralBufferPack(m_ShiftToDepthTables.pDepthToShiftTable, m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16))); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::OnShiftToDepthPropertyValueChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnShiftToDepthConfig Config; - nRetVal = GetShiftToDepthConfig(Config); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnShiftToDepthUpdate(&m_ShiftToDepthTables, &Config); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RaiseChangeEvents(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::OnDeviceS2DTablesSizeChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // free the tables, and re-init them - XnShiftToDepthFree(&m_ShiftToDepthTables); - - XnShiftToDepthConfig Config; - nRetVal = GetShiftToDepthConfig(Config); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnShiftToDepthInit(&m_ShiftToDepthTables, &Config); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RaiseChangeEvents(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnShiftToDepthStreamHelper::GetShiftToDepthTableImpl(const XnGeneralBuffer& gbValue) const -{ - XnUInt32 nTableSize = m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel); - if (gbValue.nDataSize < nTableSize) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - xnOSMemCopy(gbValue.pData, m_ShiftToDepthTables.pShiftToDepthTable, nTableSize); - return XN_STATUS_OK; -} - -XnStatus XnShiftToDepthStreamHelper::GetDepthToShiftTableImpl(const XnGeneralBuffer& gbValue) const -{ - XnUInt32 nTableSize = m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16); - if (gbValue.nDataSize < nTableSize) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - xnOSMemCopy(gbValue.pData, m_ShiftToDepthTables.pDepthToShiftTable, nTableSize); - return XN_STATUS_OK; -} - -XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::GetShiftToDepthTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; - return pStream->GetShiftToDepthTableImpl(gbValue); -} - -XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::GetDepthToShiftTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; - return pStream->GetDepthToShiftTableImpl(gbValue); -} - -XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::ShiftToDepthPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; - return pStream->OnShiftToDepthPropertyValueChanged(); -} - -XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::DeviceS2DTablesSizeChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; - return pStream->OnDeviceS2DTablesSizeChanged(); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#include "XnShiftToDepthStreamHelper.h" + +XnShiftToDepthStreamHelper::XnShiftToDepthStreamHelper(XnDeviceModule* pModule) : + m_ShiftToDepthTable(XN_STREAM_PROPERTY_S2D_TABLE, NULL, 0, NULL), + m_DepthToShiftTable(XN_STREAM_PROPERTY_D2S_TABLE, NULL, 0, NULL), + m_pModule(pModule), + m_bPropertiesAdded(FALSE) +{ + m_ShiftToDepthTable.UpdateGetCallback(GetShiftToDepthTableCallback, this); + m_DepthToShiftTable.UpdateGetCallback(GetDepthToShiftTableCallback, this); + xnOSMemSet(&m_ShiftToDepthTables, 0, sizeof(XnShiftToDepthTables)); +} + +XnShiftToDepthStreamHelper::~XnShiftToDepthStreamHelper() +{ + XnShiftToDepthStreamHelper::Free(); +} + +XnStatus XnShiftToDepthStreamHelper::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // old depth streams did not have S2D tables as actual properties. Add these properties + XnBool bDoesExist = FALSE; + nRetVal = m_pModule->DoesPropertyExist(XN_STREAM_PROPERTY_S2D_TABLE, &bDoesExist); + XN_IS_STATUS_OK(nRetVal); + + if (!bDoesExist) + { + // add properties to the module + XN_VALIDATE_ADD_PROPERTIES(m_pModule, &m_ShiftToDepthTable, &m_DepthToShiftTable); + + m_bPropertiesAdded = TRUE; + + // now create tables and register to properties + nRetVal = InitShiftToDepth(); + XN_IS_STATUS_OK(nRetVal); + } + else + { + m_ShiftToDepthTables.pShiftToDepthTable = (XnDepthPixel*)m_ShiftToDepthTable.GetValue().pData; + m_ShiftToDepthTables.pDepthToShiftTable = (XnUInt16*)m_DepthToShiftTable.GetValue().pData; + } + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::Free() +{ + XnShiftToDepthFree(&m_ShiftToDepthTables); + return XN_STATUS_OK; +} + +XnStatus XnShiftToDepthStreamHelper::InitShiftToDepth() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // register to any shift-to-depth property (so tables can be updated if needed) + const XnChar* propNames[] = + { + XN_STREAM_PROPERTY_MIN_DEPTH, + XN_STREAM_PROPERTY_MAX_DEPTH, + XN_STREAM_PROPERTY_CONST_SHIFT, + XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, + XN_STREAM_PROPERTY_PARAM_COEFF, + XN_STREAM_PROPERTY_SHIFT_SCALE, + XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, + XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, + XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE + }; + + XnUInt32 nPropCount = sizeof(propNames) / sizeof(const XnChar*); + + XnProperty* pProperty = NULL; + for (XnUInt32 i = 0; i < nPropCount; ++i) + { + nRetVal = m_pModule->GetProperty(propNames[i], &pProperty); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProperty->OnChangeEvent().Register(ShiftToDepthPropertyValueChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + } + + // register for tables size properties + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_SHIFT, &pProperty); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProperty->OnChangeEvent().Register(DeviceS2DTablesSizeChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &pProperty); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProperty->OnChangeEvent().Register(DeviceS2DTablesSizeChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + + // now init the tables + XnShiftToDepthConfig Config; + nRetVal = GetShiftToDepthConfig(Config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnShiftToDepthInit(&m_ShiftToDepthTables, &Config); + XN_IS_STATUS_OK(nRetVal); + + // replace tables buffers + m_ShiftToDepthTable.ReplaceBuffer(m_ShiftToDepthTables.pShiftToDepthTable, m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel)); + m_DepthToShiftTable.ReplaceBuffer(m_ShiftToDepthTables.pDepthToShiftTable, m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16)); + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::GetShiftToDepthConfig(XnShiftToDepthConfig& Config) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nTemp; + XnDouble dTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nZeroPlaneDistance = (XnUInt16)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &dTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.fZeroPlanePixelSize = (XnFloat)dTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, &dTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.fEmitterDCmosDistance = (XnFloat)dTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_SHIFT, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nDeviceMaxShiftValue = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nDeviceMaxDepthValue = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_CONST_SHIFT, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nConstShift = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nPixelSizeFactor = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_PARAM_COEFF, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nParamCoeff = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nShiftScale = (XnUInt32)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MIN_DEPTH, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nDepthMinCutOff = (XnDepthPixel)nTemp; + + nRetVal = m_pModule->GetProperty(XN_STREAM_PROPERTY_MAX_DEPTH, &nTemp); + XN_IS_STATUS_OK(nRetVal); + + Config.nDepthMaxCutOff = (XnDepthPixel)nTemp; + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::RaiseChangeEvents() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_ShiftToDepthTable.UnsafeUpdateValue(XnGeneralBufferPack(m_ShiftToDepthTables.pShiftToDepthTable, m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel))); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_DepthToShiftTable.UnsafeUpdateValue(XnGeneralBufferPack(m_ShiftToDepthTables.pDepthToShiftTable, m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16))); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::OnShiftToDepthPropertyValueChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnShiftToDepthConfig Config; + nRetVal = GetShiftToDepthConfig(Config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnShiftToDepthUpdate(&m_ShiftToDepthTables, &Config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RaiseChangeEvents(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::OnDeviceS2DTablesSizeChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // free the tables, and re-init them + XnShiftToDepthFree(&m_ShiftToDepthTables); + + XnShiftToDepthConfig Config; + nRetVal = GetShiftToDepthConfig(Config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnShiftToDepthInit(&m_ShiftToDepthTables, &Config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RaiseChangeEvents(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnShiftToDepthStreamHelper::GetShiftToDepthTableImpl(const XnGeneralBuffer& gbValue) const +{ + XnUInt32 nTableSize = m_ShiftToDepthTables.nShiftsCount * sizeof(XnDepthPixel); + if (gbValue.nDataSize < nTableSize) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + xnOSMemCopy(gbValue.pData, m_ShiftToDepthTables.pShiftToDepthTable, nTableSize); + return XN_STATUS_OK; +} + +XnStatus XnShiftToDepthStreamHelper::GetDepthToShiftTableImpl(const XnGeneralBuffer& gbValue) const +{ + XnUInt32 nTableSize = m_ShiftToDepthTables.nDepthsCount * sizeof(XnUInt16); + if (gbValue.nDataSize < nTableSize) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + xnOSMemCopy(gbValue.pData, m_ShiftToDepthTables.pDepthToShiftTable, nTableSize); + return XN_STATUS_OK; +} + +XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::GetShiftToDepthTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; + return pStream->GetShiftToDepthTableImpl(gbValue); +} + +XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::GetDepthToShiftTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; + return pStream->GetDepthToShiftTableImpl(gbValue); +} + +XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::ShiftToDepthPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; + return pStream->OnShiftToDepthPropertyValueChanged(); +} + +XnStatus XN_CALLBACK_TYPE XnShiftToDepthStreamHelper::DeviceS2DTablesSizeChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnShiftToDepthStreamHelper* pStream = (XnShiftToDepthStreamHelper*)pCookie; + return pStream->OnDeviceS2DTablesSizeChanged(); +} + diff --git a/Source/XnDDK/XnShiftToDepthStreamHelper.h b/Source/XnDDK/XnShiftToDepthStreamHelper.h index a409d75..aa990e5 100644 --- a/Source/XnDDK/XnShiftToDepthStreamHelper.h +++ b/Source/XnDDK/XnShiftToDepthStreamHelper.h @@ -1,70 +1,70 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ -#define __XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ - -#include -#include - -class XN_DDK_CPP_API XnShiftToDepthStreamHelper -{ -public: - XnShiftToDepthStreamHelper(XnDeviceModule* pModule); - virtual ~XnShiftToDepthStreamHelper(); - - XnStatus Init(); - XnStatus Free(); - - inline XnDepthPixel* GetShiftToDepthTable() const { return m_ShiftToDepthTables.pShiftToDepthTable; } - inline XnUInt16* GetDepthToShiftTable() const { return m_ShiftToDepthTables.pDepthToShiftTable; } - -protected: - inline XnActualGeneralProperty& ShiftToDepthTableProperty() { return m_ShiftToDepthTable; } - inline XnActualGeneralProperty& DepthToShiftTableProperty() { return m_DepthToShiftTable; } - -private: - XnStatus RaiseChangeEvents(); - XnStatus InitShiftToDepth(); - XnStatus OnShiftToDepthPropertyValueChanged(); - XnStatus OnDeviceS2DTablesSizeChanged(); - XnStatus GetShiftToDepthConfig(XnShiftToDepthConfig& Config); - XnStatus GetShiftToDepthTableImpl(const XnGeneralBuffer& gbValue) const; - XnStatus GetDepthToShiftTableImpl(const XnGeneralBuffer& gbValue) const; - - // callbacks - static XnStatus XN_CALLBACK_TYPE GetShiftToDepthTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetDepthToShiftTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ShiftToDepthPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie); - static XnStatus XN_CALLBACK_TYPE DeviceS2DTablesSizeChangedCallback(const XnProperty* pSender, void* pCookie); - - XnActualGeneralProperty m_ShiftToDepthTable; - XnActualGeneralProperty m_DepthToShiftTable; - XnShiftToDepthTables m_ShiftToDepthTables; - XnDeviceModule* m_pModule; - XnBool m_bPropertiesAdded; -}; - -#endif //__XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ +#define __XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ + +#include +#include + +class XN_DDK_CPP_API XnShiftToDepthStreamHelper +{ +public: + XnShiftToDepthStreamHelper(XnDeviceModule* pModule); + virtual ~XnShiftToDepthStreamHelper(); + + XnStatus Init(); + XnStatus Free(); + + inline XnDepthPixel* GetShiftToDepthTable() const { return m_ShiftToDepthTables.pShiftToDepthTable; } + inline XnUInt16* GetDepthToShiftTable() const { return m_ShiftToDepthTables.pDepthToShiftTable; } + +protected: + inline XnActualGeneralProperty& ShiftToDepthTableProperty() { return m_ShiftToDepthTable; } + inline XnActualGeneralProperty& DepthToShiftTableProperty() { return m_DepthToShiftTable; } + +private: + XnStatus RaiseChangeEvents(); + XnStatus InitShiftToDepth(); + XnStatus OnShiftToDepthPropertyValueChanged(); + XnStatus OnDeviceS2DTablesSizeChanged(); + XnStatus GetShiftToDepthConfig(XnShiftToDepthConfig& Config); + XnStatus GetShiftToDepthTableImpl(const XnGeneralBuffer& gbValue) const; + XnStatus GetDepthToShiftTableImpl(const XnGeneralBuffer& gbValue) const; + + // callbacks + static XnStatus XN_CALLBACK_TYPE GetShiftToDepthTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetDepthToShiftTableCallback(const XnActualGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ShiftToDepthPropertyValueChangedCallback(const XnProperty* pSender, void* pCookie); + static XnStatus XN_CALLBACK_TYPE DeviceS2DTablesSizeChangedCallback(const XnProperty* pSender, void* pCookie); + + XnActualGeneralProperty m_ShiftToDepthTable; + XnActualGeneralProperty m_DepthToShiftTable; + XnShiftToDepthTables m_ShiftToDepthTables; + XnDeviceModule* m_pModule; + XnBool m_bPropertiesAdded; +}; + +#endif //__XN_SHIFT_TO_DEPTH_STREAM_HELPER_H__ diff --git a/Source/XnDDK/XnSimpleBufferPool.cpp b/Source/XnDDK/XnSimpleBufferPool.cpp index ea0e99f..a1ee5e1 100644 --- a/Source/XnDDK/XnSimpleBufferPool.cpp +++ b/Source/XnDDK/XnSimpleBufferPool.cpp @@ -1,73 +1,73 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSimpleBufferPool.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSimpleBufferPool::XnSimpleBufferPool(XnUInt32 nBufferCount) : XnBufferPool(nBufferCount) -{} - -XnSimpleBufferPool::~XnSimpleBufferPool() -{ - FreeAll(TRUE); -} - -XnStatus XnSimpleBufferPool::AllocateBuffers() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first free old ones - FreeAll(FALSE); - - // now allocate new - for (XnUInt32 i = 0; i < m_nBufferCount; ++i) - { - XnBufferInPool* pBufferInPool; - XN_VALIDATE_NEW(pBufferInPool, XnBufferInPool); - nRetVal = pBufferInPool->Allocate(m_nBufferSize); - XN_IS_STATUS_OK(nRetVal); - pBufferInPool->m_nID = i; - - // add it to all list - m_AllBuffers.AddLast(pBufferInPool); - // and to free list - m_FreeBuffers.AddLast(pBufferInPool); - } - - return (XN_STATUS_OK); -} - -void XnSimpleBufferPool::DestroyBuffer(XnBufferInPool* pBuffer) -{ - XN_DELETE(pBuffer); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSimpleBufferPool.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSimpleBufferPool::XnSimpleBufferPool(XnUInt32 nBufferCount) : XnBufferPool(nBufferCount) +{} + +XnSimpleBufferPool::~XnSimpleBufferPool() +{ + FreeAll(TRUE); +} + +XnStatus XnSimpleBufferPool::AllocateBuffers() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first free old ones + FreeAll(FALSE); + + // now allocate new + for (XnUInt32 i = 0; i < m_nBufferCount; ++i) + { + XnBufferInPool* pBufferInPool; + XN_VALIDATE_NEW(pBufferInPool, XnBufferInPool); + nRetVal = pBufferInPool->Allocate(m_nBufferSize); + XN_IS_STATUS_OK(nRetVal); + pBufferInPool->m_nID = i; + + // add it to all list + m_AllBuffers.AddLast(pBufferInPool); + // and to free list + m_FreeBuffers.AddLast(pBufferInPool); + } + + return (XN_STATUS_OK); +} + +void XnSimpleBufferPool::DestroyBuffer(XnBufferInPool* pBuffer) +{ + XN_DELETE(pBuffer); +} + diff --git a/Source/XnDDK/XnSimpleBufferPool.h b/Source/XnDDK/XnSimpleBufferPool.h index 55ceb1f..2e94be9 100644 --- a/Source/XnDDK/XnSimpleBufferPool.h +++ b/Source/XnDDK/XnSimpleBufferPool.h @@ -1,51 +1,51 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SIMPLE_BUFFER_POOL_H__ -#define __XN_SIMPLE_BUFFER_POOL_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnBufferPool.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSimpleBufferPool : public XnBufferPool -{ -public: - XnSimpleBufferPool(XnUInt32 nBufferCount); - ~XnSimpleBufferPool(); - -protected: - virtual XnStatus AllocateBuffers(); - virtual void DestroyBuffer(XnBufferInPool* pBuffer); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SIMPLE_BUFFER_POOL_H__ +#define __XN_SIMPLE_BUFFER_POOL_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnBufferPool.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSimpleBufferPool : public XnBufferPool +{ +public: + XnSimpleBufferPool(XnUInt32 nBufferCount); + ~XnSimpleBufferPool(); + +protected: + virtual XnStatus AllocateBuffers(); + virtual void DestroyBuffer(XnBufferInPool* pBuffer); +}; + #endif // __XN_SIMPLE_BUFFER_POOL_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnStreamData.cpp b/Source/XnDDK/XnStreamData.cpp index 0b6e425..e434b67 100644 --- a/Source/XnDDK/XnStreamData.cpp +++ b/Source/XnDDK/XnStreamData.cpp @@ -1,197 +1,197 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDataInternal.h" -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_DDK_API XnStatus XnStreamDataCreateNoBuffer(XnStreamData** ppStreamOutput, const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_OUTPUT_PTR(ppStreamOutput); - - // allocate struct - XN_VALIDATE_CALLOC(*ppStreamOutput, XnStreamData, 1); - XnStreamData* pStreamOutput = *ppStreamOutput; - - // allocate internal data - pStreamOutput->pInternal = (XnStreamDataInternal*)xnOSCalloc(1, sizeof(XnStreamDataInternal)); - if (pStreamOutput->pInternal == NULL) - { - XnStreamDataDestroy(ppStreamOutput); - return (XN_STATUS_ALLOC_FAILED); - } - - // fill internal data - pStreamOutput->pInternal->bAllocated = FALSE; - pStreamOutput->pInternal->nAllocSize = 0; - pStreamOutput->pInternal->UpdateMode = XN_STREAM_DATA_UPDATE_AUTOMATICALLY; - pStreamOutput->pInternal->Callback = NULL; - pStreamOutput->pInternal->pLockedBuffer = NULL; - - // take name - xnOSStrCopy(pStreamOutput->StreamName, StreamName, XN_DEVICE_MAX_STRING_LENGTH); - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnStreamDataCreate(XnStreamData** ppStreamOutput, const XnChar* StreamName, XnUInt32 nAllocSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamDataCreateNoBuffer(ppStreamOutput, StreamName); - XN_IS_STATUS_OK(nRetVal); - - XnStreamData* pStreamOutput = *ppStreamOutput; - - // allocate buffer - nRetVal = XnStreamDataUpdateSize(pStreamOutput, nAllocSize); - if (nRetVal != XN_STATUS_OK) - { - XnStreamDataDestroy(ppStreamOutput); - return nRetVal; - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnStreamDataUpdateSize(XnStreamData* pStreamOutput, XnUInt32 nAllocSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - // allocate new memory - void* pNew = xnOSMallocAligned(nAllocSize, XN_DEFAULT_MEM_ALIGN); - if (pNew == NULL) - return (XN_STATUS_ALLOC_FAILED); - - // zero it - xnOSMemSet(pNew, 0, nAllocSize); - - // free the buffer if it is allocated - XN_ALIGNED_FREE_AND_NULL(pStreamOutput->pData); - - // and now set new buffer - pStreamOutput->pData = pNew; - - // and size - pStreamOutput->pInternal->nAllocSize = nAllocSize; - - pStreamOutput->pInternal->bAllocated = TRUE; - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataDestroy(XnStreamData** ppStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(ppStreamOutput); - XnStreamData* pStreamOutput = *ppStreamOutput; - - if (pStreamOutput != NULL) - { - // only free buffer if allocated - if (pStreamOutput->pInternal->nAllocSize != 0) - { - xnOSFreeAligned(pStreamOutput->pData); - } - - pStreamOutput->pData = NULL; - - XN_FREE_AND_NULL(pStreamOutput->pInternal); - - XN_FREE_AND_NULL(*ppStreamOutput); - } - - return (XN_STATUS_OK); -} - -XN_DDK_API XnStatus XnStreamDataSetUpdateMode(XnStreamData* pStreamOutput, XnStreamDataUpdateMode UpdateMode, XnStreamOutputNotificationCallback Callback, void* pCallbackData) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - if (UpdateMode == XN_STREAM_DATA_UPDATE_NOTIFY && Callback == NULL) - return XN_STATUS_DEVICE_BAD_PARAM; - - pStreamOutput->pInternal->UpdateMode = UpdateMode; - pStreamOutput->pInternal->Callback = Callback; - pStreamOutput->pInternal->pCallbackData = pCallbackData; - - return XN_STATUS_OK; -} - -void XnStreamOutputCallCallbackFunction(XnStreamData* pStreamOutput, XnUInt32 nNeededSize) -{ - if (pStreamOutput->pInternal->Callback != NULL) - { - pStreamOutput->pInternal->Callback(pStreamOutput, pStreamOutput->pInternal->pCallbackData, nNeededSize); - } -} - -XN_DDK_API XnStatus XnStreamDataCheckSize(XnStreamData* pStreamOutput, XnUInt32 nNeededSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - // if not allocated, then nothing to check - if (!pStreamOutput->pInternal->bAllocated) - return (XN_STATUS_OK); - - if (nNeededSize <= pStreamOutput->pInternal->nAllocSize) - return (XN_STATUS_OK); - - // oh no! we don't have enough space - - if (pStreamOutput->pInternal->UpdateMode == XN_STREAM_DATA_UPDATE_AUTOMATICALLY) - { - // reallocate - nRetVal = XnStreamDataUpdateSize(pStreamOutput, nNeededSize); - XN_IS_STATUS_OK(nRetVal); - - // and call callback - XnStreamOutputCallCallbackFunction(pStreamOutput, nNeededSize); - return XN_STATUS_OK; - } - else if (pStreamOutput->pInternal->UpdateMode == XN_STREAM_DATA_UPDATE_NOTIFY) - { - // let client decide - XnStreamOutputCallCallbackFunction(pStreamOutput, nNeededSize); - - // check if it was fixed - if (nNeededSize <= pStreamOutput->pInternal->nAllocSize) - return XN_STATUS_OK; - } - - // if we got here, problem still exists - return XN_STATUS_STREAM_OUTPUT_BUFFER_TOO_SMALL; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDataInternal.h" +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_DDK_API XnStatus XnStreamDataCreateNoBuffer(XnStreamData** ppStreamOutput, const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_OUTPUT_PTR(ppStreamOutput); + + // allocate struct + XN_VALIDATE_CALLOC(*ppStreamOutput, XnStreamData, 1); + XnStreamData* pStreamOutput = *ppStreamOutput; + + // allocate internal data + pStreamOutput->pInternal = (XnStreamDataInternal*)xnOSCalloc(1, sizeof(XnStreamDataInternal)); + if (pStreamOutput->pInternal == NULL) + { + XnStreamDataDestroy(ppStreamOutput); + return (XN_STATUS_ALLOC_FAILED); + } + + // fill internal data + pStreamOutput->pInternal->bAllocated = FALSE; + pStreamOutput->pInternal->nAllocSize = 0; + pStreamOutput->pInternal->UpdateMode = XN_STREAM_DATA_UPDATE_AUTOMATICALLY; + pStreamOutput->pInternal->Callback = NULL; + pStreamOutput->pInternal->pLockedBuffer = NULL; + + // take name + xnOSStrCopy(pStreamOutput->StreamName, StreamName, XN_DEVICE_MAX_STRING_LENGTH); + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnStreamDataCreate(XnStreamData** ppStreamOutput, const XnChar* StreamName, XnUInt32 nAllocSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamDataCreateNoBuffer(ppStreamOutput, StreamName); + XN_IS_STATUS_OK(nRetVal); + + XnStreamData* pStreamOutput = *ppStreamOutput; + + // allocate buffer + nRetVal = XnStreamDataUpdateSize(pStreamOutput, nAllocSize); + if (nRetVal != XN_STATUS_OK) + { + XnStreamDataDestroy(ppStreamOutput); + return nRetVal; + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnStreamDataUpdateSize(XnStreamData* pStreamOutput, XnUInt32 nAllocSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + // allocate new memory + void* pNew = xnOSMallocAligned(nAllocSize, XN_DEFAULT_MEM_ALIGN); + if (pNew == NULL) + return (XN_STATUS_ALLOC_FAILED); + + // zero it + xnOSMemSet(pNew, 0, nAllocSize); + + // free the buffer if it is allocated + XN_ALIGNED_FREE_AND_NULL(pStreamOutput->pData); + + // and now set new buffer + pStreamOutput->pData = pNew; + + // and size + pStreamOutput->pInternal->nAllocSize = nAllocSize; + + pStreamOutput->pInternal->bAllocated = TRUE; + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataDestroy(XnStreamData** ppStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(ppStreamOutput); + XnStreamData* pStreamOutput = *ppStreamOutput; + + if (pStreamOutput != NULL) + { + // only free buffer if allocated + if (pStreamOutput->pInternal->nAllocSize != 0) + { + xnOSFreeAligned(pStreamOutput->pData); + } + + pStreamOutput->pData = NULL; + + XN_FREE_AND_NULL(pStreamOutput->pInternal); + + XN_FREE_AND_NULL(*ppStreamOutput); + } + + return (XN_STATUS_OK); +} + +XN_DDK_API XnStatus XnStreamDataSetUpdateMode(XnStreamData* pStreamOutput, XnStreamDataUpdateMode UpdateMode, XnStreamOutputNotificationCallback Callback, void* pCallbackData) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + if (UpdateMode == XN_STREAM_DATA_UPDATE_NOTIFY && Callback == NULL) + return XN_STATUS_DEVICE_BAD_PARAM; + + pStreamOutput->pInternal->UpdateMode = UpdateMode; + pStreamOutput->pInternal->Callback = Callback; + pStreamOutput->pInternal->pCallbackData = pCallbackData; + + return XN_STATUS_OK; +} + +void XnStreamOutputCallCallbackFunction(XnStreamData* pStreamOutput, XnUInt32 nNeededSize) +{ + if (pStreamOutput->pInternal->Callback != NULL) + { + pStreamOutput->pInternal->Callback(pStreamOutput, pStreamOutput->pInternal->pCallbackData, nNeededSize); + } +} + +XN_DDK_API XnStatus XnStreamDataCheckSize(XnStreamData* pStreamOutput, XnUInt32 nNeededSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + // if not allocated, then nothing to check + if (!pStreamOutput->pInternal->bAllocated) + return (XN_STATUS_OK); + + if (nNeededSize <= pStreamOutput->pInternal->nAllocSize) + return (XN_STATUS_OK); + + // oh no! we don't have enough space + + if (pStreamOutput->pInternal->UpdateMode == XN_STREAM_DATA_UPDATE_AUTOMATICALLY) + { + // reallocate + nRetVal = XnStreamDataUpdateSize(pStreamOutput, nNeededSize); + XN_IS_STATUS_OK(nRetVal); + + // and call callback + XnStreamOutputCallCallbackFunction(pStreamOutput, nNeededSize); + return XN_STATUS_OK; + } + else if (pStreamOutput->pInternal->UpdateMode == XN_STREAM_DATA_UPDATE_NOTIFY) + { + // let client decide + XnStreamOutputCallCallbackFunction(pStreamOutput, nNeededSize); + + // check if it was fixed + if (nNeededSize <= pStreamOutput->pInternal->nAllocSize) + return XN_STATUS_OK; + } + + // if we got here, problem still exists + return XN_STATUS_STREAM_OUTPUT_BUFFER_TOO_SMALL; +} diff --git a/Source/XnDDK/XnStreamDataInternal.h b/Source/XnDDK/XnStreamDataInternal.h index 510e756..4742e78 100644 --- a/Source/XnDDK/XnStreamDataInternal.h +++ b/Source/XnDDK/XnStreamDataInternal.h @@ -1,62 +1,62 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_DATA_INTERNAL_H__ -#define __XN_STREAM_DATA_INTERNAL_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnBuffer; - -struct XnStreamDataInternal -{ - XnStreamDataUpdateMode UpdateMode; - XnStreamOutputNotificationCallback Callback; - void* pCallbackData; - XnBool bAllocated; - XnUInt32 nAllocSize; - XnBuffer* pLockedBuffer; -}; - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- -/** -* Creates a new stream output object which does not allocate data. -* -* @param ppStreamOutput [out] A pointer to the newly created object. -* @param StreamName [in] The name of the stream that this buffer will be used for. -* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. -*/ -XN_DDK_API XnStatus XnStreamDataCreateNoBuffer(XnStreamData** ppStreamOutput, const XnChar* StreamName); - -#endif //__XN_STREAM_DATA_INTERNAL_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_DATA_INTERNAL_H__ +#define __XN_STREAM_DATA_INTERNAL_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnBuffer; + +struct XnStreamDataInternal +{ + XnStreamDataUpdateMode UpdateMode; + XnStreamOutputNotificationCallback Callback; + void* pCallbackData; + XnBool bAllocated; + XnUInt32 nAllocSize; + XnBuffer* pLockedBuffer; +}; + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- +/** +* Creates a new stream output object which does not allocate data. +* +* @param ppStreamOutput [out] A pointer to the newly created object. +* @param StreamName [in] The name of the stream that this buffer will be used for. +* @param nAllocSize [in] The number of bytes to allocate for the pData buffer. +*/ +XN_DDK_API XnStatus XnStreamDataCreateNoBuffer(XnStreamData** ppStreamOutput, const XnChar* StreamName); + +#endif //__XN_STREAM_DATA_INTERNAL_H__ diff --git a/Source/XnDDK/XnStreamDataSet.cpp b/Source/XnDDK/XnStreamDataSet.cpp index 9e21ba1..82ad0f7 100644 --- a/Source/XnDDK/XnStreamDataSet.cpp +++ b/Source/XnDDK/XnStreamDataSet.cpp @@ -1,161 +1,161 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDataSetInternal.h" -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XN_DDK_API XnStatus XnStreamDataSetCreate(XnStreamDataSet** ppStreamOutputSet) -{ - XN_VALIDATE_OUTPUT_PTR(ppStreamOutputSet); - - // allocate struct - XN_VALIDATE_CALLOC(*ppStreamOutputSet, XnStreamDataSet, 1); - XnStreamDataSet* pSet = (*ppStreamOutputSet); - - // allocate hash table - pSet->pHash = XN_NEW(XnStreamDataHash); - if (pSet->pHash == NULL) - { - XnStreamDataSetDestroy(ppStreamOutputSet); - return XN_STATUS_ALLOC_FAILED; - } - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataSetDestroy(XnStreamDataSet** ppStreamOutputSet) -{ - XN_VALIDATE_INPUT_PTR(ppStreamOutputSet); - - XnStreamDataSet* pSet = (*ppStreamOutputSet); - if (pSet != NULL) - { - for (XnStreamDataHash::Iterator it = pSet->pHash->begin(); it != pSet->pHash->end(); ++it) - { - XnStreamData* pStreamData = it.Value(); - XnStreamDataDestroy(&pStreamData); - } - - // free hash table - XN_DELETE(pSet->pHash); - - // free struct - XN_FREE_AND_NULL(*ppStreamOutputSet); - } - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataSetAdd(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - // make sure another object of this stream is not already in set - XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->end(); - if (XN_STATUS_NO_MATCH != pStreamOutputSet->pHash->Find(pStreamOutput->StreamName, it)) - return XN_STATUS_STREAM_OUTPUT_SET_ALREADY_IN_SET; - - return pStreamOutputSet->pHash->Set(pStreamOutput->StreamName, pStreamOutput); -} - -XN_DDK_API XnStatus XnStreamDataSetRemove(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - for (XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->begin(); it != pStreamOutputSet->pHash->end(); ++it) - { - if (pStreamOutput == it.Value()) - { - pStreamOutputSet->pHash->Remove(it); - break; - } - } - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataSetRemoveByName(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - XN_VALIDATE_INPUT_PTR(StreamName); - - pStreamOutputSet->pHash->Remove(StreamName); - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataSetGet(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName, XnStreamData** ppStreamOutput) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - XN_VALIDATE_INPUT_PTR(StreamName); - XN_VALIDATE_OUTPUT_PTR(ppStreamOutput); - - XnStreamData* pData; - XnStatus nRetVal = pStreamOutputSet->pHash->Get(StreamName, pData); - XN_IS_STATUS_OK(nRetVal); - - *ppStreamOutput = pData; - - return XN_STATUS_OK; -} - -XN_DDK_API XnStatus XnStreamDataSetCopyToArray(const XnStreamDataSet* pStreamOutputSet, XnStreamData** apStreamOutputs, XnUInt32* pnCount) -{ - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - XN_VALIDATE_INPUT_PTR(pnCount); - - // first check if we have enough space - XnUInt32 nCount = pStreamOutputSet->pHash->Size(); - XnUInt32 nArraySize = *pnCount; - - *pnCount = nCount; - - if (nArraySize < nCount) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - // now copy - XnUInt32 nIndex = 0; - for (XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->begin(); it != pStreamOutputSet->pHash->end(); ++it) - { - apStreamOutputs[nIndex] = it.Value(); - nIndex++; - } - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDataSetInternal.h" +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XN_DDK_API XnStatus XnStreamDataSetCreate(XnStreamDataSet** ppStreamOutputSet) +{ + XN_VALIDATE_OUTPUT_PTR(ppStreamOutputSet); + + // allocate struct + XN_VALIDATE_CALLOC(*ppStreamOutputSet, XnStreamDataSet, 1); + XnStreamDataSet* pSet = (*ppStreamOutputSet); + + // allocate hash table + pSet->pHash = XN_NEW(XnStreamDataHash); + if (pSet->pHash == NULL) + { + XnStreamDataSetDestroy(ppStreamOutputSet); + return XN_STATUS_ALLOC_FAILED; + } + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataSetDestroy(XnStreamDataSet** ppStreamOutputSet) +{ + XN_VALIDATE_INPUT_PTR(ppStreamOutputSet); + + XnStreamDataSet* pSet = (*ppStreamOutputSet); + if (pSet != NULL) + { + for (XnStreamDataHash::Iterator it = pSet->pHash->begin(); it != pSet->pHash->end(); ++it) + { + XnStreamData* pStreamData = it.Value(); + XnStreamDataDestroy(&pStreamData); + } + + // free hash table + XN_DELETE(pSet->pHash); + + // free struct + XN_FREE_AND_NULL(*ppStreamOutputSet); + } + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataSetAdd(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + // make sure another object of this stream is not already in set + XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->end(); + if (XN_STATUS_NO_MATCH != pStreamOutputSet->pHash->Find(pStreamOutput->StreamName, it)) + return XN_STATUS_STREAM_OUTPUT_SET_ALREADY_IN_SET; + + return pStreamOutputSet->pHash->Set(pStreamOutput->StreamName, pStreamOutput); +} + +XN_DDK_API XnStatus XnStreamDataSetRemove(XnStreamDataSet* pStreamOutputSet, XnStreamData* pStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + for (XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->begin(); it != pStreamOutputSet->pHash->end(); ++it) + { + if (pStreamOutput == it.Value()) + { + pStreamOutputSet->pHash->Remove(it); + break; + } + } + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataSetRemoveByName(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + XN_VALIDATE_INPUT_PTR(StreamName); + + pStreamOutputSet->pHash->Remove(StreamName); + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataSetGet(XnStreamDataSet* pStreamOutputSet, const XnChar* StreamName, XnStreamData** ppStreamOutput) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + XN_VALIDATE_INPUT_PTR(StreamName); + XN_VALIDATE_OUTPUT_PTR(ppStreamOutput); + + XnStreamData* pData; + XnStatus nRetVal = pStreamOutputSet->pHash->Get(StreamName, pData); + XN_IS_STATUS_OK(nRetVal); + + *ppStreamOutput = pData; + + return XN_STATUS_OK; +} + +XN_DDK_API XnStatus XnStreamDataSetCopyToArray(const XnStreamDataSet* pStreamOutputSet, XnStreamData** apStreamOutputs, XnUInt32* pnCount) +{ + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + XN_VALIDATE_INPUT_PTR(pnCount); + + // first check if we have enough space + XnUInt32 nCount = pStreamOutputSet->pHash->Size(); + XnUInt32 nArraySize = *pnCount; + + *pnCount = nCount; + + if (nArraySize < nCount) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + // now copy + XnUInt32 nIndex = 0; + for (XnStreamDataHash::Iterator it = pStreamOutputSet->pHash->begin(); it != pStreamOutputSet->pHash->end(); ++it) + { + apStreamOutputs[nIndex] = it.Value(); + nIndex++; + } + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnStreamDataSetInternal.h b/Source/XnDDK/XnStreamDataSetInternal.h index 331dd1c..e005231 100644 --- a/Source/XnDDK/XnStreamDataSetInternal.h +++ b/Source/XnDDK/XnStreamDataSetInternal.h @@ -1,42 +1,42 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#ifndef __XN_STREAM_DATA_SET_INTERNAL_H__ -#define __XN_STREAM_DATA_SET_INTERNAL_H__ - -#include "XnStreamDataSet.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -XN_DECLARE_STRINGS_HASH(XnStreamData*, XnStreamDataHash) - -struct XnStreamDataSet -{ - XnStreamDataHash* pHash; -}; - -#endif //__XN_STREAM_DATA_SET_INTERNAL_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#ifndef __XN_STREAM_DATA_SET_INTERNAL_H__ +#define __XN_STREAM_DATA_SET_INTERNAL_H__ + +#include "XnStreamDataSet.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +XN_DECLARE_STRINGS_HASH(XnStreamData*, XnStreamDataHash) + +struct XnStreamDataSet +{ + XnStreamDataHash* pHash; +}; + +#endif //__XN_STREAM_DATA_SET_INTERNAL_H__ diff --git a/Source/XnDDK/XnStreamDevice.cpp b/Source/XnDDK/XnStreamDevice.cpp index c7d527e..bca718a 100644 --- a/Source/XnDDK/XnStreamDevice.cpp +++ b/Source/XnDDK/XnStreamDevice.cpp @@ -1,119 +1,119 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDevice.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamDevice::XnStreamDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : - XnDeviceBase(strName, FALSE), - m_pDataPacker(NULL), - m_nInternalBufferSize(nInternalBufferSize) -{} - -XnStreamDevice::~XnStreamDevice() -{ - DestroyImpl(FALSE); -} - -XnStatus XnStreamDevice::Destroy() -{ - XnDeviceBase::Destroy(); - DestroyImpl(TRUE); - return XN_STATUS_OK; -} - -void XnStreamDevice::DestroyImpl(XnBool bHasVTable) -{ - if (m_pDataPacker != NULL) - { - XN_DELETE(m_pDataPacker); - m_pDataPacker = NULL; - } - - if (m_pIOStream != NULL && bHasVTable) - { - // we can't destroy IO stream if we no longer have V-table - DestroyIOStreamImpl(m_pIOStream); - m_pIOStream = NULL; - } -} - -XnStatus XnStreamDevice::Seek(XnUInt64 nTimestamp) -{ - return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; -} - -XnStatus XnStreamDevice::SeekFrame(XnUInt32 nFrameID) -{ - return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; -} - -XnStatus XnStreamDevice::InitPacker(const XnChar *strConnectionString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create the stream - nRetVal = CreateIOStreamImpl(strConnectionString, m_pIOStream); - XN_IS_STATUS_OK(nRetVal); - - // create the data packer - m_pDataPacker = XN_NEW(XnDataPacker, m_pIOStream, m_nInternalBufferSize); - if (m_pDataPacker == NULL) - { - DestroyIOStreamImpl(m_pIOStream); - return XN_STATUS_ALLOC_FAILED; - } - - nRetVal = m_pDataPacker->Init(); - if (nRetVal != XN_STATUS_OK) - { - DestroyIOStreamImpl(m_pIOStream); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamDevice::FindStream(const XnChar *strName, XnStreamDeviceStreamHolder **ppHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModuleHolder* pHolder; - nRetVal = XnDeviceBase::FindStream(strName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - // we create all streams, so we know their type - *ppHolder = (XnStreamDeviceStreamHolder*)pHolder; - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDevice.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamDevice::XnStreamDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : + XnDeviceBase(strName, FALSE), + m_pDataPacker(NULL), + m_nInternalBufferSize(nInternalBufferSize) +{} + +XnStreamDevice::~XnStreamDevice() +{ + DestroyImpl(FALSE); +} + +XnStatus XnStreamDevice::Destroy() +{ + XnDeviceBase::Destroy(); + DestroyImpl(TRUE); + return XN_STATUS_OK; +} + +void XnStreamDevice::DestroyImpl(XnBool bHasVTable) +{ + if (m_pDataPacker != NULL) + { + XN_DELETE(m_pDataPacker); + m_pDataPacker = NULL; + } + + if (m_pIOStream != NULL && bHasVTable) + { + // we can't destroy IO stream if we no longer have V-table + DestroyIOStreamImpl(m_pIOStream); + m_pIOStream = NULL; + } +} + +XnStatus XnStreamDevice::Seek(XnUInt64 nTimestamp) +{ + return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; +} + +XnStatus XnStreamDevice::SeekFrame(XnUInt32 nFrameID) +{ + return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; +} + +XnStatus XnStreamDevice::InitPacker(const XnChar *strConnectionString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // create the stream + nRetVal = CreateIOStreamImpl(strConnectionString, m_pIOStream); + XN_IS_STATUS_OK(nRetVal); + + // create the data packer + m_pDataPacker = XN_NEW(XnDataPacker, m_pIOStream, m_nInternalBufferSize); + if (m_pDataPacker == NULL) + { + DestroyIOStreamImpl(m_pIOStream); + return XN_STATUS_ALLOC_FAILED; + } + + nRetVal = m_pDataPacker->Init(); + if (nRetVal != XN_STATUS_OK) + { + DestroyIOStreamImpl(m_pIOStream); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamDevice::FindStream(const XnChar *strName, XnStreamDeviceStreamHolder **ppHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModuleHolder* pHolder; + nRetVal = XnDeviceBase::FindStream(strName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + // we create all streams, so we know their type + *ppHolder = (XnStreamDeviceStreamHolder*)pHolder; + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnStreamDevice.h b/Source/XnDDK/XnStreamDevice.h index a82ba21..72483fb 100644 --- a/Source/XnDDK/XnStreamDevice.h +++ b/Source/XnDDK/XnStreamDevice.h @@ -1,70 +1,70 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_DEVICE_H__ -#define __XN_STREAM_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceBase.h" -#include "XnDataPacker.h" -#include "XnStreamDeviceStreamHolder.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamDevice : public XnDeviceBase -{ -public: - XnStreamDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); - ~XnStreamDevice(); - - XnStatus Destroy(); - - XnStatus Seek(XnUInt64 nTimestamp); - XnStatus SeekFrame(XnUInt32 nFrameID); - -protected: - XnStatus FindStream(const XnChar* strName, XnStreamDeviceStreamHolder** ppHolder); - - inline XnIOStream* GetIOStream() { return m_pIOStream; } - inline XnDataPacker* GetDataPacker() { return m_pDataPacker; } - - XnStatus InitPacker(const XnChar* strConnectionString); - - void DestroyImpl(XnBool bHasVTable); - - virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) = 0; - virtual void DestroyIOStreamImpl(XnIOStream* pStream) = 0; - -private: - XnIOStream* m_pIOStream; - XnDataPacker* m_pDataPacker; - XnUInt32 m_nInternalBufferSize; -}; - -#endif //__XN_STREAM_DEVICE_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_DEVICE_H__ +#define __XN_STREAM_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceBase.h" +#include "XnDataPacker.h" +#include "XnStreamDeviceStreamHolder.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamDevice : public XnDeviceBase +{ +public: + XnStreamDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); + ~XnStreamDevice(); + + XnStatus Destroy(); + + XnStatus Seek(XnUInt64 nTimestamp); + XnStatus SeekFrame(XnUInt32 nFrameID); + +protected: + XnStatus FindStream(const XnChar* strName, XnStreamDeviceStreamHolder** ppHolder); + + inline XnIOStream* GetIOStream() { return m_pIOStream; } + inline XnDataPacker* GetDataPacker() { return m_pDataPacker; } + + XnStatus InitPacker(const XnChar* strConnectionString); + + void DestroyImpl(XnBool bHasVTable); + + virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) = 0; + virtual void DestroyIOStreamImpl(XnIOStream* pStream) = 0; + +private: + XnIOStream* m_pIOStream; + XnDataPacker* m_pDataPacker; + XnUInt32 m_nInternalBufferSize; +}; + +#endif //__XN_STREAM_DEVICE_H__ diff --git a/Source/XnDDK/XnStreamDeviceStreamHolder.cpp b/Source/XnDDK/XnStreamDeviceStreamHolder.cpp index febe781..e55f719 100644 --- a/Source/XnDDK/XnStreamDeviceStreamHolder.cpp +++ b/Source/XnDDK/XnStreamDeviceStreamHolder.cpp @@ -1,232 +1,232 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDeviceStreamHolder.h" -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamDeviceStreamHolder::XnStreamDeviceStreamHolder(XnDeviceStream* pStream, XnBool bCompressionIsReadOnly) : - XnDeviceModuleHolder(pStream, TRUE), - m_Compression(XN_STREAM_PROPERTY_COMPRESSION, XN_COMPRESSION_NONE), - m_pCodec(NULL) -{ - if (!bCompressionIsReadOnly) - { - m_Compression.UpdateSetCallbackToDefault(); - } -} - -XnStatus XnStreamDeviceStreamHolder::Init(const XnActualPropertiesHash* pProps) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_ADD_PROPERTIES(GetStream(), &m_Compression); - - nRetVal = XnDeviceModuleHolder::Init(pProps); - XN_IS_STATUS_OK(nRetVal); - - // create codec - nRetVal = m_CodecProperties.Set(&m_Compression, &m_Compression); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Compression.OnChangeEvent().Register(CodecPropertyChangedCallback, this, NULL); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ChooseCodec(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamDeviceStreamHolder::Free() -{ - XN_DELETE(m_pCodec); - m_pCodec = NULL; - - return XnDeviceModuleHolder::Free(); -} - -XnStatus XnStreamDeviceStreamHolder::ChooseCodec() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create new codec (we also need to register on all the properties) - XnCodec* pCodec; - XnPropertiesList CodecProps; - - switch (GetCompression()) - { - case XN_COMPRESSION_NONE: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, XnUncompressedCodec); - } - break; - case XN_COMPRESSION_16Z: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zCodec); - } - break; - case XN_COMPRESSION_16Z_EMB_TABLE: - { - // first we need to find max depth - XnIntProperty* pDeviceMaxDepthProp; - nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &pDeviceMaxDepthProp); - XN_IS_STATUS_OK(nRetVal); - - XnUInt64 nMaxDepth; - nRetVal = pDeviceMaxDepthProp->GetValue(&nMaxDepth); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = CodecProps.AddLast(pDeviceMaxDepthProp); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zEmbTablesCodec, (XnDepthPixel)nMaxDepth); - } - break; - case XN_COMPRESSION_COLOR_8Z: - { - XN_VALIDATE_NEW_AND_INIT(pCodec, Xn8zCodec); - } - break; - case XN_COMPRESSION_JPEG: - { - // check what is the output format - XnIntProperty* pOutputFormatProp; - nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, &pOutputFormatProp); - XN_IS_STATUS_OK(nRetVal); - - XnUInt64 nOutputFormat; - nRetVal = pOutputFormatProp->GetValue(&nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - XnBool bRGB = FALSE; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - bRGB = FALSE; - break; - case XN_OUTPUT_FORMAT_RGB24: - bRGB = TRUE; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory currently supports JPEG codec only for streams of type Gray8 or RGB24!"); - } - - nRetVal = CodecProps.AddLast(pOutputFormatProp); - XN_IS_STATUS_OK(nRetVal); - - // X res - XnIntProperty* pXResProp; - nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_X_RES, &pXResProp); - XN_IS_STATUS_OK(nRetVal); - - XnUInt64 nXRes; - nRetVal = pXResProp->GetValue(&nXRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = CodecProps.AddLast(pXResProp); - XN_IS_STATUS_OK(nRetVal); - - // Y res - XnIntProperty* pYResProp; - nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_Y_RES, &pYResProp); - XN_IS_STATUS_OK(nRetVal); - - XnUInt64 nYRes; - nRetVal = pYResProp->GetValue(&nYRes); - XN_IS_STATUS_OK(nRetVal); - - // Cropping - XnGeneralProperty* pCroppingProp; - nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_CROPPING, &pCroppingProp); - XN_IS_STATUS_OK(nRetVal); - - XnCropping cropping; - nRetVal = pCroppingProp->GetValue(XN_PACK_GENERAL_BUFFER(cropping)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = CodecProps.AddLast(pCroppingProp); - XN_IS_STATUS_OK(nRetVal); - - // calc x,y - if (cropping.bEnabled) - { - nXRes = cropping.nXSize; - nYRes = cropping.nYSize; - } - - XN_VALIDATE_NEW_AND_INIT(pCodec, XnJpegCodec, bRGB, (XnUInt32)nXRes, (XnUInt32)nYRes); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory does not support compression type %d", GetCompression()); - } - - // register to new props - for (XnPropertiesList::Iterator it = CodecProps.begin(); it != CodecProps.end(); ++it) - { - XnProperty* pProp = *it; - - XnPropertiesHash::Iterator hashIt = m_CodecProperties.end(); - nRetVal = m_CodecProperties.Find(pProp, hashIt); - if (nRetVal == XN_STATUS_NO_MATCH) - { - XnCallbackHandle hCallbackDummy; - nRetVal = pProp->OnChangeEvent().Register(CodecPropertyChangedCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_CodecProperties.Set(pProp, NULL); - XN_IS_STATUS_OK(nRetVal); - } - else - { - XN_IS_STATUS_OK(nRetVal); - } - } - - // replace it - XN_DELETE(m_pCodec); - m_pCodec = pCodec; - - return (XN_STATUS_OK); -} - -XnStatus XnStreamDeviceStreamHolder::CodecPropertyChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnStreamDeviceStreamHolder* pThis = (XnStreamDeviceStreamHolder*)pCookie; - return pThis->ChooseCodec(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDeviceStreamHolder.h" +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamDeviceStreamHolder::XnStreamDeviceStreamHolder(XnDeviceStream* pStream, XnBool bCompressionIsReadOnly) : + XnDeviceModuleHolder(pStream, TRUE), + m_Compression(XN_STREAM_PROPERTY_COMPRESSION, XN_COMPRESSION_NONE), + m_pCodec(NULL) +{ + if (!bCompressionIsReadOnly) + { + m_Compression.UpdateSetCallbackToDefault(); + } +} + +XnStatus XnStreamDeviceStreamHolder::Init(const XnActualPropertiesHash* pProps) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_ADD_PROPERTIES(GetStream(), &m_Compression); + + nRetVal = XnDeviceModuleHolder::Init(pProps); + XN_IS_STATUS_OK(nRetVal); + + // create codec + nRetVal = m_CodecProperties.Set(&m_Compression, &m_Compression); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Compression.OnChangeEvent().Register(CodecPropertyChangedCallback, this, NULL); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ChooseCodec(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamDeviceStreamHolder::Free() +{ + XN_DELETE(m_pCodec); + m_pCodec = NULL; + + return XnDeviceModuleHolder::Free(); +} + +XnStatus XnStreamDeviceStreamHolder::ChooseCodec() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // create new codec (we also need to register on all the properties) + XnCodec* pCodec; + XnPropertiesList CodecProps; + + switch (GetCompression()) + { + case XN_COMPRESSION_NONE: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, XnUncompressedCodec); + } + break; + case XN_COMPRESSION_16Z: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zCodec); + } + break; + case XN_COMPRESSION_16Z_EMB_TABLE: + { + // first we need to find max depth + XnIntProperty* pDeviceMaxDepthProp; + nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &pDeviceMaxDepthProp); + XN_IS_STATUS_OK(nRetVal); + + XnUInt64 nMaxDepth; + nRetVal = pDeviceMaxDepthProp->GetValue(&nMaxDepth); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = CodecProps.AddLast(pDeviceMaxDepthProp); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zEmbTablesCodec, (XnDepthPixel)nMaxDepth); + } + break; + case XN_COMPRESSION_COLOR_8Z: + { + XN_VALIDATE_NEW_AND_INIT(pCodec, Xn8zCodec); + } + break; + case XN_COMPRESSION_JPEG: + { + // check what is the output format + XnIntProperty* pOutputFormatProp; + nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, &pOutputFormatProp); + XN_IS_STATUS_OK(nRetVal); + + XnUInt64 nOutputFormat; + nRetVal = pOutputFormatProp->GetValue(&nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + XnBool bRGB = FALSE; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + bRGB = FALSE; + break; + case XN_OUTPUT_FORMAT_RGB24: + bRGB = TRUE; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory currently supports JPEG codec only for streams of type Gray8 or RGB24!"); + } + + nRetVal = CodecProps.AddLast(pOutputFormatProp); + XN_IS_STATUS_OK(nRetVal); + + // X res + XnIntProperty* pXResProp; + nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_X_RES, &pXResProp); + XN_IS_STATUS_OK(nRetVal); + + XnUInt64 nXRes; + nRetVal = pXResProp->GetValue(&nXRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = CodecProps.AddLast(pXResProp); + XN_IS_STATUS_OK(nRetVal); + + // Y res + XnIntProperty* pYResProp; + nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_Y_RES, &pYResProp); + XN_IS_STATUS_OK(nRetVal); + + XnUInt64 nYRes; + nRetVal = pYResProp->GetValue(&nYRes); + XN_IS_STATUS_OK(nRetVal); + + // Cropping + XnGeneralProperty* pCroppingProp; + nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_CROPPING, &pCroppingProp); + XN_IS_STATUS_OK(nRetVal); + + XnCropping cropping; + nRetVal = pCroppingProp->GetValue(XN_PACK_GENERAL_BUFFER(cropping)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = CodecProps.AddLast(pCroppingProp); + XN_IS_STATUS_OK(nRetVal); + + // calc x,y + if (cropping.bEnabled) + { + nXRes = cropping.nXSize; + nYRes = cropping.nYSize; + } + + XN_VALIDATE_NEW_AND_INIT(pCodec, XnJpegCodec, bRGB, (XnUInt32)nXRes, (XnUInt32)nYRes); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory does not support compression type %d", GetCompression()); + } + + // register to new props + for (XnPropertiesList::Iterator it = CodecProps.begin(); it != CodecProps.end(); ++it) + { + XnProperty* pProp = *it; + + XnPropertiesHash::Iterator hashIt = m_CodecProperties.end(); + nRetVal = m_CodecProperties.Find(pProp, hashIt); + if (nRetVal == XN_STATUS_NO_MATCH) + { + XnCallbackHandle hCallbackDummy; + nRetVal = pProp->OnChangeEvent().Register(CodecPropertyChangedCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_CodecProperties.Set(pProp, NULL); + XN_IS_STATUS_OK(nRetVal); + } + else + { + XN_IS_STATUS_OK(nRetVal); + } + } + + // replace it + XN_DELETE(m_pCodec); + m_pCodec = pCodec; + + return (XN_STATUS_OK); +} + +XnStatus XnStreamDeviceStreamHolder::CodecPropertyChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnStreamDeviceStreamHolder* pThis = (XnStreamDeviceStreamHolder*)pCookie; + return pThis->ChooseCodec(); +} diff --git a/Source/XnDDK/XnStreamDeviceStreamHolder.h b/Source/XnDDK/XnStreamDeviceStreamHolder.h index a01ed06..31d2803 100644 --- a/Source/XnDDK/XnStreamDeviceStreamHolder.h +++ b/Source/XnDDK/XnStreamDeviceStreamHolder.h @@ -1,70 +1,70 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_DEVICE_STREAM_HOLDER_H__ -#define __XN_STREAM_DEVICE_STREAM_HOLDER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceModuleHolder.h" -#include "XnDeviceStream.h" -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamDeviceStreamHolder : public XnDeviceModuleHolder -{ -public: - XnStreamDeviceStreamHolder(XnDeviceStream* pStream, XnBool bCompressionIsReadOnly); - - virtual XnStatus Init(const XnActualPropertiesHash* pProps); - virtual XnStatus Free(); - - inline XnDeviceStream* GetStream() { return (XnDeviceStream*)GetModule(); } - - inline XnCompressionFormats GetCompression() const { return (XnCompressionFormats)m_Compression.GetValue(); } - - inline XnCodec* GetCodec() const { return m_pCodec; } - -protected: - XnActualIntProperty& CompressionProperty() { return m_Compression; } - -private: - XnStatus ChooseCodec(); - - static XnStatus XN_CALLBACK_TYPE CodecPropertyChangedCallback(const XnProperty* pSender, void* pCookie); - - XnActualIntProperty m_Compression; - XnCodec* m_pCodec; - - XN_DECLARE_DEFAULT_HASH(XnProperty*, XnValue, XnPropertiesHash) - XnPropertiesHash m_CodecProperties; -}; - -#endif //__XN_STREAM_DEVICE_STREAM_HOLDER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_DEVICE_STREAM_HOLDER_H__ +#define __XN_STREAM_DEVICE_STREAM_HOLDER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceModuleHolder.h" +#include "XnDeviceStream.h" +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamDeviceStreamHolder : public XnDeviceModuleHolder +{ +public: + XnStreamDeviceStreamHolder(XnDeviceStream* pStream, XnBool bCompressionIsReadOnly); + + virtual XnStatus Init(const XnActualPropertiesHash* pProps); + virtual XnStatus Free(); + + inline XnDeviceStream* GetStream() { return (XnDeviceStream*)GetModule(); } + + inline XnCompressionFormats GetCompression() const { return (XnCompressionFormats)m_Compression.GetValue(); } + + inline XnCodec* GetCodec() const { return m_pCodec; } + +protected: + XnActualIntProperty& CompressionProperty() { return m_Compression; } + +private: + XnStatus ChooseCodec(); + + static XnStatus XN_CALLBACK_TYPE CodecPropertyChangedCallback(const XnProperty* pSender, void* pCookie); + + XnActualIntProperty m_Compression; + XnCodec* m_pCodec; + + XN_DECLARE_DEFAULT_HASH(XnProperty*, XnValue, XnPropertiesHash) + XnPropertiesHash m_CodecProperties; +}; + +#endif //__XN_STREAM_DEVICE_STREAM_HOLDER_H__ diff --git a/Source/XnDDK/XnStreamReaderDevice.cpp b/Source/XnDDK/XnStreamReaderDevice.cpp index d0f6dc0..2441b67 100644 --- a/Source/XnDDK/XnStreamReaderDevice.cpp +++ b/Source/XnDDK/XnStreamReaderDevice.cpp @@ -1,516 +1,516 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamReaderDevice.h" -#include "XnPropertySetInternal.h" -#include "XnStreamReaderStream.h" -#include "XnStreamReaderStreamHolder.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamReaderDevice::XnStreamReaderDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : - XnStreamDevice(strName, nInternalBufferSize) -{} - -XnStreamReaderDevice::~XnStreamReaderDevice() -{} - -XnStatus XnStreamReaderDevice::InitImpl(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // we will init the device using state from the stream, instead of the one from user. - // the one from user will be used to set properties afterwards. - - // first open the stream - nRetVal = InitPacker(pDeviceConfig->cpConnectionString); - XN_IS_STATUS_OK(nRetVal); - - // create a property set - XnPropertySet* pSet; - nRetVal = XnPropertySetCreate(&pSet); - XN_IS_STATUS_OK(nRetVal); - - // read initial state (we assume first object in the stream is the initial state) - nRetVal = ReadInitialState(pSet); - if (nRetVal != XN_STATUS_OK) - { - XnPropertySetDestroy(&pSet); - return (nRetVal); - } - - nRetVal = SetInitialState(pDeviceConfig, pSet); - if (nRetVal != XN_STATUS_OK) - { - XnPropertySetDestroy(&pSet); - return (nRetVal); - } - - // destroy the property set (we don't need it anymore) - nRetVal = XnPropertySetDestroy(&pSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadInitialState(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read an object from data packer - XnPackedDataType nType; - nRetVal = GetDataPacker()->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType != XN_PACKED_PROPERTY_SET) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Stream does not start with a property set!"); - } - - nRetVal = GetDataPacker()->ReadPropertySet(pSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::SetInitialState(const XnDeviceConfig* pDeviceConfig, XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Fix state (remove some properties that we don't wish to reflect in reader device) - XnActualPropertiesHash* pDeviceModule = NULL; - if (XN_STATUS_OK == pSet->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModule)) - { - pDeviceModule->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); - pDeviceModule->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); - } - - // now init base using this state (this will also create module DEVICE) - XnDeviceConfig initConfig; - initConfig.cpConnectionString = pDeviceConfig->cpConnectionString; - initConfig.DeviceMode = pDeviceConfig->DeviceMode; - initConfig.pInitialValues = pSet; - initConfig.SharingMode = pDeviceConfig->SharingMode; - - nRetVal = XnStreamDevice::InitImpl(&initConfig); - XN_IS_STATUS_OK(nRetVal); - - // now create the rest of the modules and streams (DEVICE was already created) - XnPropertySetData* pPropSetData = pSet->pData; - for (XnPropertySetData::ConstIterator it = pPropSetData->begin(); it != pPropSetData->end(); ++it) - { - // ignore module DEVICE - if (strcmp(XN_MODULE_NAME_DEVICE, it.Key()) == 0) - { - continue; - } - - // check if this is a stream - XnActualPropertiesHash::ConstIterator itProp = it.Value()->end(); - if (XN_STATUS_OK == it.Value()->Find(XN_STREAM_PROPERTY_TYPE, itProp)) - { - XnActualStringProperty* pTypeProp = (XnActualStringProperty*)itProp.Value(); - nRetVal = HandleNewStream(pTypeProp->GetValue(), it.Key(), it.Value()); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // this is module. create it - XnDeviceModuleHolder* pHolder = NULL; - nRetVal = CreateModule(it.Key(), &pHolder); - XN_IS_STATUS_OK(nRetVal); - - // set its props - nRetVal = pHolder->Init(it.Value()); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(pHolder); - return (nRetVal); - } - - // and add it - nRetVal = AddModule(pHolder); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(pHolder); - return (nRetVal); - } - } - } // modules loop - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamReaderStream* pStream; - XN_VALIDATE_NEW(pStream, XnStreamReaderStream, StreamType, StreamName); - - XnStreamReaderStreamHolder* pHolder = XN_NEW(XnStreamReaderStreamHolder, pStream); - if (pHolder == NULL) - { - XN_DELETE(pStream); - return XN_STATUS_ALLOC_FAILED; - } - - *ppStreamHolder = pHolder; - - return (XN_STATUS_OK); -} - -void XnStreamReaderDevice::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) -{ - XN_DELETE(pStreamHolder->GetModule()); - XN_DELETE(pStreamHolder); -} - -XnStatus XnStreamReaderDevice::ReadNextEventFromStream(XnPackedDataType* pnObjectType /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnPackedDataType nObjectType; - - nRetVal = GetDataPacker()->ReadNextObject(&nObjectType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandlePackedObject(nObjectType); - XN_IS_STATUS_OK(nRetVal); - - if (pnObjectType != NULL) - { - *pnObjectType = nObjectType; - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandlePackedObject(XnPackedDataType nObjectType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nObjectType) - { - case XN_PACKED_NEW_STREAM: - nRetVal = ReadNewStream(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STREAM_REMOVED: - nRetVal = ReadStreamRemoved(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_INT_PROPERTY: - nRetVal = ReadIntProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_REAL_PROPERTY: - nRetVal = ReadRealProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STRING_PROPERTY: - nRetVal = ReadStringProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_GENERAL_PROPERTY: - nRetVal = ReadGeneralProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STREAM_DATA: - nRetVal = ReadStreamData(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_END: - nRetVal = HandleEndOfStream(); - XN_IS_STATUS_OK(nRetVal); - break; - default: - XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Unexpected packed type: %d", nObjectType); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadNewStream() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - - // create property set - XnPropertySet* pPropertySet = NULL; - nRetVal = XnPropertySetCreate(&pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - // read from stream - nRetVal = GetDataPacker()->ReadNewStream(strType, strName, pPropertySet); - - if (nRetVal == XN_STATUS_OK) - { - nRetVal = ValidateOnlyModule(pPropertySet, strName); - } - - if (nRetVal == XN_STATUS_OK) - { - // create it - nRetVal = HandleNewStream(strType, strName, pPropertySet->pData->begin().Value()); - } - - XnPropertySetDestroy(&pPropertySet); - - return (nRetVal); -} - -XnStatus XnStreamReaderDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamDevice::CreateStreamImpl(strType, strName, pInitialValues); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadStreamRemoved() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read stream name - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - - nRetVal = GetDataPacker()->ReadStreamRemoved(strName); - XN_IS_STATUS_OK(nRetVal); - - // remove it - nRetVal = HandleStreamRemoved(strName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleStreamRemoved(const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamReaderDevice::DestroyStream(strName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadIntProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt64 nValue; - - // read change data - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleIntProperty(strModule, strProp, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleIntProperty(const XnChar *strModule, const XnChar *strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // ignore some properties - if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) - { - return (XN_STATUS_OK); - } - - // find module - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // update prop - nRetVal = pModule->UnsafeUpdateProperty(strName, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadRealProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnDouble dValue; - - // read change data - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &dValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleRealProperty(strModule, strProp, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleRealProperty(const XnChar *strModule, const XnChar *strName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find module - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // update prop - nRetVal = pModule->UnsafeUpdateProperty(strName, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadStringProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - - // read change data - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleStringProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleStringProperty(const XnChar *strModule, const XnChar *strName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find module - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // update prop - nRetVal = pModule->UnsafeUpdateProperty(strName, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadGeneralProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnGeneralBuffer gbValue; - - // read change data - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &gbValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleGeneralProperty(strModule, strProp, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find module - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // update prop - nRetVal = pModule->UnsafeUpdateProperty(strName, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::ReadStreamData() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamData props; - XnCompressionFormats nCompression; - XnUInt32 nCompressedSize; - nRetVal = GetDataPacker()->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleStreamData(&props, nCompression, nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find the stream - XnStreamDeviceStreamHolder* pStreamHolder; - nRetVal = FindStream(pDataProps->StreamName, &pStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); - - XnStreamData* pStreamData = pStream->GetStreamData(); - - // check size - nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->ReadStreamData(pStreamData, pStreamHolder->GetCodec()); - XN_IS_STATUS_OK(nRetVal); - - pStream->NewDataAvailable(); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderDevice::HandleEndOfStream() -{ - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamReaderDevice.h" +#include "XnPropertySetInternal.h" +#include "XnStreamReaderStream.h" +#include "XnStreamReaderStreamHolder.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamReaderDevice::XnStreamReaderDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : + XnStreamDevice(strName, nInternalBufferSize) +{} + +XnStreamReaderDevice::~XnStreamReaderDevice() +{} + +XnStatus XnStreamReaderDevice::InitImpl(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // we will init the device using state from the stream, instead of the one from user. + // the one from user will be used to set properties afterwards. + + // first open the stream + nRetVal = InitPacker(pDeviceConfig->cpConnectionString); + XN_IS_STATUS_OK(nRetVal); + + // create a property set + XnPropertySet* pSet; + nRetVal = XnPropertySetCreate(&pSet); + XN_IS_STATUS_OK(nRetVal); + + // read initial state (we assume first object in the stream is the initial state) + nRetVal = ReadInitialState(pSet); + if (nRetVal != XN_STATUS_OK) + { + XnPropertySetDestroy(&pSet); + return (nRetVal); + } + + nRetVal = SetInitialState(pDeviceConfig, pSet); + if (nRetVal != XN_STATUS_OK) + { + XnPropertySetDestroy(&pSet); + return (nRetVal); + } + + // destroy the property set (we don't need it anymore) + nRetVal = XnPropertySetDestroy(&pSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadInitialState(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read an object from data packer + XnPackedDataType nType; + nRetVal = GetDataPacker()->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType != XN_PACKED_PROPERTY_SET) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Stream does not start with a property set!"); + } + + nRetVal = GetDataPacker()->ReadPropertySet(pSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::SetInitialState(const XnDeviceConfig* pDeviceConfig, XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Fix state (remove some properties that we don't wish to reflect in reader device) + XnActualPropertiesHash* pDeviceModule = NULL; + if (XN_STATUS_OK == pSet->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModule)) + { + pDeviceModule->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); + pDeviceModule->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); + } + + // now init base using this state (this will also create module DEVICE) + XnDeviceConfig initConfig; + initConfig.cpConnectionString = pDeviceConfig->cpConnectionString; + initConfig.DeviceMode = pDeviceConfig->DeviceMode; + initConfig.pInitialValues = pSet; + initConfig.SharingMode = pDeviceConfig->SharingMode; + + nRetVal = XnStreamDevice::InitImpl(&initConfig); + XN_IS_STATUS_OK(nRetVal); + + // now create the rest of the modules and streams (DEVICE was already created) + XnPropertySetData* pPropSetData = pSet->pData; + for (XnPropertySetData::ConstIterator it = pPropSetData->begin(); it != pPropSetData->end(); ++it) + { + // ignore module DEVICE + if (strcmp(XN_MODULE_NAME_DEVICE, it.Key()) == 0) + { + continue; + } + + // check if this is a stream + XnActualPropertiesHash::ConstIterator itProp = it.Value()->end(); + if (XN_STATUS_OK == it.Value()->Find(XN_STREAM_PROPERTY_TYPE, itProp)) + { + XnActualStringProperty* pTypeProp = (XnActualStringProperty*)itProp.Value(); + nRetVal = HandleNewStream(pTypeProp->GetValue(), it.Key(), it.Value()); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // this is module. create it + XnDeviceModuleHolder* pHolder = NULL; + nRetVal = CreateModule(it.Key(), &pHolder); + XN_IS_STATUS_OK(nRetVal); + + // set its props + nRetVal = pHolder->Init(it.Value()); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(pHolder); + return (nRetVal); + } + + // and add it + nRetVal = AddModule(pHolder); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(pHolder); + return (nRetVal); + } + } + } // modules loop + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamReaderStream* pStream; + XN_VALIDATE_NEW(pStream, XnStreamReaderStream, StreamType, StreamName); + + XnStreamReaderStreamHolder* pHolder = XN_NEW(XnStreamReaderStreamHolder, pStream); + if (pHolder == NULL) + { + XN_DELETE(pStream); + return XN_STATUS_ALLOC_FAILED; + } + + *ppStreamHolder = pHolder; + + return (XN_STATUS_OK); +} + +void XnStreamReaderDevice::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) +{ + XN_DELETE(pStreamHolder->GetModule()); + XN_DELETE(pStreamHolder); +} + +XnStatus XnStreamReaderDevice::ReadNextEventFromStream(XnPackedDataType* pnObjectType /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnPackedDataType nObjectType; + + nRetVal = GetDataPacker()->ReadNextObject(&nObjectType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandlePackedObject(nObjectType); + XN_IS_STATUS_OK(nRetVal); + + if (pnObjectType != NULL) + { + *pnObjectType = nObjectType; + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandlePackedObject(XnPackedDataType nObjectType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nObjectType) + { + case XN_PACKED_NEW_STREAM: + nRetVal = ReadNewStream(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STREAM_REMOVED: + nRetVal = ReadStreamRemoved(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_INT_PROPERTY: + nRetVal = ReadIntProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_REAL_PROPERTY: + nRetVal = ReadRealProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STRING_PROPERTY: + nRetVal = ReadStringProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_GENERAL_PROPERTY: + nRetVal = ReadGeneralProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STREAM_DATA: + nRetVal = ReadStreamData(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_END: + nRetVal = HandleEndOfStream(); + XN_IS_STATUS_OK(nRetVal); + break; + default: + XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Unexpected packed type: %d", nObjectType); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadNewStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + + // create property set + XnPropertySet* pPropertySet = NULL; + nRetVal = XnPropertySetCreate(&pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + // read from stream + nRetVal = GetDataPacker()->ReadNewStream(strType, strName, pPropertySet); + + if (nRetVal == XN_STATUS_OK) + { + nRetVal = ValidateOnlyModule(pPropertySet, strName); + } + + if (nRetVal == XN_STATUS_OK) + { + // create it + nRetVal = HandleNewStream(strType, strName, pPropertySet->pData->begin().Value()); + } + + XnPropertySetDestroy(&pPropertySet); + + return (nRetVal); +} + +XnStatus XnStreamReaderDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamDevice::CreateStreamImpl(strType, strName, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadStreamRemoved() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read stream name + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + + nRetVal = GetDataPacker()->ReadStreamRemoved(strName); + XN_IS_STATUS_OK(nRetVal); + + // remove it + nRetVal = HandleStreamRemoved(strName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleStreamRemoved(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamReaderDevice::DestroyStream(strName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadIntProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt64 nValue; + + // read change data + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleIntProperty(strModule, strProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleIntProperty(const XnChar *strModule, const XnChar *strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // ignore some properties + if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) + { + return (XN_STATUS_OK); + } + + // find module + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // update prop + nRetVal = pModule->UnsafeUpdateProperty(strName, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadRealProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnDouble dValue; + + // read change data + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &dValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleRealProperty(strModule, strProp, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleRealProperty(const XnChar *strModule, const XnChar *strName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find module + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // update prop + nRetVal = pModule->UnsafeUpdateProperty(strName, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadStringProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + + // read change data + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleStringProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleStringProperty(const XnChar *strModule, const XnChar *strName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find module + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // update prop + nRetVal = pModule->UnsafeUpdateProperty(strName, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadGeneralProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnGeneralBuffer gbValue; + + // read change data + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &gbValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleGeneralProperty(strModule, strProp, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find module + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // update prop + nRetVal = pModule->UnsafeUpdateProperty(strName, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::ReadStreamData() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamData props; + XnCompressionFormats nCompression; + XnUInt32 nCompressedSize; + nRetVal = GetDataPacker()->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleStreamData(&props, nCompression, nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find the stream + XnStreamDeviceStreamHolder* pStreamHolder; + nRetVal = FindStream(pDataProps->StreamName, &pStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); + + XnStreamData* pStreamData = pStream->GetStreamData(); + + // check size + nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->ReadStreamData(pStreamData, pStreamHolder->GetCodec()); + XN_IS_STATUS_OK(nRetVal); + + pStream->NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderDevice::HandleEndOfStream() +{ + return (XN_STATUS_OK); +} diff --git a/Source/XnDDK/XnStreamReaderDevice.h b/Source/XnDDK/XnStreamReaderDevice.h index 6f91d17..2b55956 100644 --- a/Source/XnDDK/XnStreamReaderDevice.h +++ b/Source/XnDDK/XnStreamReaderDevice.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_READER_DEVICE_H__ -#define __XN_STREAM_READER_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDevice.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamReaderDevice : public XnStreamDevice -{ -public: - XnStreamReaderDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); - ~XnStreamReaderDevice(); - - XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - -protected: - XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); - void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); - - XnStatus SetInitialState(const XnDeviceConfig* pDeviceConfig, XnPropertySet* pSet); - - virtual XnStatus ReadInitialState(XnPropertySet* pSet); - virtual XnStatus ReadNextEventFromStream(XnPackedDataType* pnObjectType = NULL); - virtual XnStatus HandlePackedObject(XnPackedDataType nObjectType); - virtual XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); - virtual XnStatus HandleStreamRemoved(const XnChar* strName); - virtual XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); - virtual XnStatus HandleRealProperty(const XnChar* strModule, const XnChar* strName, XnDouble dValue); - virtual XnStatus HandleStringProperty(const XnChar* strModule, const XnChar* strName, const XnChar* strValue); - virtual XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); - virtual XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); - virtual XnStatus HandleEndOfStream(); - -private: - XnStatus ReadNewStream(); - XnStatus ReadStreamRemoved(); - XnStatus ReadIntProperty(); - XnStatus ReadRealProperty(); - XnStatus ReadStringProperty(); - XnStatus ReadGeneralProperty(); - XnStatus ReadStreamData(); -}; - -#endif //__XN_STREAM_READER_DEVICE_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_READER_DEVICE_H__ +#define __XN_STREAM_READER_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDevice.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamReaderDevice : public XnStreamDevice +{ +public: + XnStreamReaderDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); + ~XnStreamReaderDevice(); + + XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + +protected: + XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); + void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); + + XnStatus SetInitialState(const XnDeviceConfig* pDeviceConfig, XnPropertySet* pSet); + + virtual XnStatus ReadInitialState(XnPropertySet* pSet); + virtual XnStatus ReadNextEventFromStream(XnPackedDataType* pnObjectType = NULL); + virtual XnStatus HandlePackedObject(XnPackedDataType nObjectType); + virtual XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); + virtual XnStatus HandleStreamRemoved(const XnChar* strName); + virtual XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); + virtual XnStatus HandleRealProperty(const XnChar* strModule, const XnChar* strName, XnDouble dValue); + virtual XnStatus HandleStringProperty(const XnChar* strModule, const XnChar* strName, const XnChar* strValue); + virtual XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); + virtual XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); + virtual XnStatus HandleEndOfStream(); + +private: + XnStatus ReadNewStream(); + XnStatus ReadStreamRemoved(); + XnStatus ReadIntProperty(); + XnStatus ReadRealProperty(); + XnStatus ReadStringProperty(); + XnStatus ReadGeneralProperty(); + XnStatus ReadStreamData(); +}; + +#endif //__XN_STREAM_READER_DEVICE_H__ diff --git a/Source/XnDDK/XnStreamReaderStream.cpp b/Source/XnDDK/XnStreamReaderStream.cpp index 0b5f10d..dd5d6e8 100644 --- a/Source/XnDDK/XnStreamReaderStream.cpp +++ b/Source/XnDDK/XnStreamReaderStream.cpp @@ -1,142 +1,142 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamReaderStream.h" -#include "XnStreamDataInternal.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamReaderStream::XnStreamReaderStream(const XnChar* strType, const XnChar* strName) : - XnDeviceStream(strType, strName), - m_pLastData(NULL), - m_nLastFrameIDFromStream(0) -{} - -XnStreamReaderStream::~XnStreamReaderStream() -{ - XnStreamReaderStream::Free(); -} - -XnStatus XnStreamReaderStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - // register for size change (so we can realloc stream data) - nRetVal = RequiredSizeProperty().OnChangeEvent().Register(RequiredSizeChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - - // and create stream data - nRetVal = XnStreamDataCreate(&m_pLastData, GetName(), GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderStream::Free() -{ - if (m_pLastData != NULL) - { - XnStreamDataDestroy(&m_pLastData); - m_pLastData = NULL; - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderStream::ReadImpl(XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - pStreamData->nFrameID = m_pLastData->nFrameID; - pStreamData->nTimestamp = m_pLastData->nTimestamp; - - if (pStreamData->pInternal->bAllocated) - { - // don't take more than required size - pStreamData->nDataSize = XN_MIN(m_pLastData->nDataSize, GetRequiredDataSize()); - xnOSMemCopy(pStreamData->pData, m_pLastData->pData, pStreamData->nDataSize); - } - else - { - pStreamData->nDataSize = m_pLastData->nDataSize; - pStreamData->pData = m_pLastData->pData; - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const -{ - // we use the same size we have now - *pnRequiredSize = GetRequiredDataSize(); - return XN_STATUS_OK; -} - -void XnStreamReaderStream::NewDataAvailable() -{ - m_pLastData->nFrameID = ++m_nLastFrameIDFromStream; - XnDeviceStream::NewDataAvailable(m_pLastData->nTimestamp, m_pLastData->nFrameID); -} - -void XnStreamReaderStream::ReMarkDataAsNew() -{ - XnDeviceStream::NewDataAvailable(m_pLastData->nTimestamp, m_pLastData->nFrameID); -} - -void XnStreamReaderStream::Reset() -{ - m_nLastFrameIDFromStream = 0; - xnOSMemSet(m_pLastData->pData, 0, m_pLastData->pInternal->nAllocSize); - m_pLastData->nDataSize = 0; - m_pLastData->nFrameID = 0; - m_pLastData->nTimestamp = 0; - m_pLastData->bIsNew = FALSE; - XnDeviceStream::ResetLastTimestampAndFrameID(); -} - -XnStatus XnStreamReaderStream::OnRequiredSizeChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamDataUpdateSize(m_pLastData, GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderStream::RequiredSizeChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnStreamReaderStream* pThis = (XnStreamReaderStream*)pCookie; - return pThis->OnRequiredSizeChanged(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamReaderStream.h" +#include "XnStreamDataInternal.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamReaderStream::XnStreamReaderStream(const XnChar* strType, const XnChar* strName) : + XnDeviceStream(strType, strName), + m_pLastData(NULL), + m_nLastFrameIDFromStream(0) +{} + +XnStreamReaderStream::~XnStreamReaderStream() +{ + XnStreamReaderStream::Free(); +} + +XnStatus XnStreamReaderStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + // register for size change (so we can realloc stream data) + nRetVal = RequiredSizeProperty().OnChangeEvent().Register(RequiredSizeChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + + // and create stream data + nRetVal = XnStreamDataCreate(&m_pLastData, GetName(), GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderStream::Free() +{ + if (m_pLastData != NULL) + { + XnStreamDataDestroy(&m_pLastData); + m_pLastData = NULL; + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderStream::ReadImpl(XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + pStreamData->nFrameID = m_pLastData->nFrameID; + pStreamData->nTimestamp = m_pLastData->nTimestamp; + + if (pStreamData->pInternal->bAllocated) + { + // don't take more than required size + pStreamData->nDataSize = XN_MIN(m_pLastData->nDataSize, GetRequiredDataSize()); + xnOSMemCopy(pStreamData->pData, m_pLastData->pData, pStreamData->nDataSize); + } + else + { + pStreamData->nDataSize = m_pLastData->nDataSize; + pStreamData->pData = m_pLastData->pData; + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const +{ + // we use the same size we have now + *pnRequiredSize = GetRequiredDataSize(); + return XN_STATUS_OK; +} + +void XnStreamReaderStream::NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID) +{ + m_pLastData->nFrameID = ++m_nLastFrameIDFromStream; + XnDeviceStream::NewDataAvailable(m_pLastData->nTimestamp, m_pLastData->nFrameID); +} + +void XnStreamReaderStream::ReMarkDataAsNew() +{ + XnDeviceStream::NewDataAvailable(m_pLastData->nTimestamp, m_pLastData->nFrameID); +} + +void XnStreamReaderStream::Reset() +{ + m_nLastFrameIDFromStream = 0; + xnOSMemSet(m_pLastData->pData, 0, m_pLastData->pInternal->nAllocSize); + m_pLastData->nDataSize = 0; + m_pLastData->nFrameID = 0; + m_pLastData->nTimestamp = 0; + m_pLastData->bIsNew = FALSE; + XnDeviceStream::ResetLastTimestampAndFrameID(); +} + +XnStatus XnStreamReaderStream::OnRequiredSizeChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamDataUpdateSize(m_pLastData, GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderStream::RequiredSizeChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnStreamReaderStream* pThis = (XnStreamReaderStream*)pCookie; + return pThis->OnRequiredSizeChanged(); +} diff --git a/Source/XnDDK/XnStreamReaderStream.h b/Source/XnDDK/XnStreamReaderStream.h index 3f21763..429ab05 100644 --- a/Source/XnDDK/XnStreamReaderStream.h +++ b/Source/XnDDK/XnStreamReaderStream.h @@ -1,68 +1,68 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_READER_STREAM_H__ -#define __XN_STREAM_READER_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceStream.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamReaderStream : public XnDeviceStream -{ -public: - XnStreamReaderStream(const XnChar* strType, const XnChar* strName); - ~XnStreamReaderStream(); - - XnStatus Init(); - XnStatus Free(); - - inline XnStreamData* GetStreamData() { return m_pLastData; } - void NewDataAvailable(); - void ReMarkDataAsNew(); - void Reset(); - -protected: - XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } - XnStatus ReadImpl(XnStreamData* pStreamOutput); - XnStatus Mirror(XnStreamData* pStreamData) const { return XN_STATUS_OK; } - - XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; - -private: - XnStatus OnRequiredSizeChanged(); - - static XnStatus XN_CALLBACK_TYPE RequiredSizeChangedCallback(const XnProperty* pSender, void* pCookie); - - XnStreamData* m_pLastData; - XnUInt32 m_nLastFrameIDFromStream; -}; - -#endif //__XN_STREAM_READER_STREAM_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_READER_STREAM_H__ +#define __XN_STREAM_READER_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceStream.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamReaderStream : public XnDeviceStream +{ +public: + XnStreamReaderStream(const XnChar* strType, const XnChar* strName); + ~XnStreamReaderStream(); + + XnStatus Init(); + XnStatus Free(); + + inline XnStreamData* GetStreamData() { return m_pLastData; } + virtual void NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID); + void ReMarkDataAsNew(); + void Reset(); + +protected: + XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } + XnStatus ReadImpl(XnStreamData* pStreamOutput); + XnStatus Mirror(XnStreamData* pStreamData) const { return XN_STATUS_OK; } + + XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; + +private: + XnStatus OnRequiredSizeChanged(); + + static XnStatus XN_CALLBACK_TYPE RequiredSizeChangedCallback(const XnProperty* pSender, void* pCookie); + + XnStreamData* m_pLastData; + XnUInt32 m_nLastFrameIDFromStream; +}; + +#endif //__XN_STREAM_READER_STREAM_H__ diff --git a/Source/XnDDK/XnStreamReaderStreamHolder.cpp b/Source/XnDDK/XnStreamReaderStreamHolder.cpp index 63b948f..0587ef2 100644 --- a/Source/XnDDK/XnStreamReaderStreamHolder.cpp +++ b/Source/XnDDK/XnStreamReaderStreamHolder.cpp @@ -1,78 +1,78 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamReaderStreamHolder.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamReaderStreamHolder::XnStreamReaderStreamHolder(XnDeviceStream* pStream) : - XnStreamDeviceStreamHolder(pStream, TRUE), - m_pS2DHelper(NULL) -{} - -XnStreamReaderStreamHolder::~XnStreamReaderStreamHolder() -{ - XnStreamReaderStreamHolder::Free(); -} - -XnStatus XnStreamReaderStreamHolder::Init(const XnActualPropertiesHash* pProps) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamDeviceStreamHolder::Init(pProps); - XN_IS_STATUS_OK(nRetVal); - - if (strcmp(GetStream()->GetType(), XN_STREAM_TYPE_DEPTH) == 0) - { - XN_VALIDATE_NEW(m_pS2DHelper, XnShiftToDepthStreamHelper, GetStream()); - nRetVal = m_pS2DHelper->Init(); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamReaderStreamHolder::Free() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_pS2DHelper != NULL) - { - m_pS2DHelper->Free(); - XN_DELETE(m_pS2DHelper); - m_pS2DHelper = NULL; - } - - XnStreamDeviceStreamHolder::Free(); - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamReaderStreamHolder.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamReaderStreamHolder::XnStreamReaderStreamHolder(XnDeviceStream* pStream) : + XnStreamDeviceStreamHolder(pStream, TRUE), + m_pS2DHelper(NULL) +{} + +XnStreamReaderStreamHolder::~XnStreamReaderStreamHolder() +{ + XnStreamReaderStreamHolder::Free(); +} + +XnStatus XnStreamReaderStreamHolder::Init(const XnActualPropertiesHash* pProps) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamDeviceStreamHolder::Init(pProps); + XN_IS_STATUS_OK(nRetVal); + + if (strcmp(GetStream()->GetType(), XN_STREAM_TYPE_DEPTH) == 0) + { + XN_VALIDATE_NEW(m_pS2DHelper, XnShiftToDepthStreamHelper, GetStream()); + nRetVal = m_pS2DHelper->Init(); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamReaderStreamHolder::Free() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pS2DHelper != NULL) + { + m_pS2DHelper->Free(); + XN_DELETE(m_pS2DHelper); + m_pS2DHelper = NULL; + } + + XnStreamDeviceStreamHolder::Free(); + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnStreamReaderStreamHolder.h b/Source/XnDDK/XnStreamReaderStreamHolder.h index e48a049..ee61274 100644 --- a/Source/XnDDK/XnStreamReaderStreamHolder.h +++ b/Source/XnDDK/XnStreamReaderStreamHolder.h @@ -1,53 +1,53 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_READER_STREAM_HOLDER_H__ -#define __XN_STREAM_READER_STREAM_HOLDER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDeviceStreamHolder.h" -#include "XnShiftToDepthStreamHelper.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamReaderStreamHolder : public XnStreamDeviceStreamHolder -{ -public: - XnStreamReaderStreamHolder(XnDeviceStream* pStream); - ~XnStreamReaderStreamHolder(); - - virtual XnStatus Init(const XnActualPropertiesHash* pProps); - virtual XnStatus Free(); - -private: - // helpers - XnShiftToDepthStreamHelper* m_pS2DHelper; -}; - -#endif //__XN_STREAM_READER_STREAM_HOLDER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_READER_STREAM_HOLDER_H__ +#define __XN_STREAM_READER_STREAM_HOLDER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDeviceStreamHolder.h" +#include "XnShiftToDepthStreamHelper.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamReaderStreamHolder : public XnStreamDeviceStreamHolder +{ +public: + XnStreamReaderStreamHolder(XnDeviceStream* pStream); + ~XnStreamReaderStreamHolder(); + + virtual XnStatus Init(const XnActualPropertiesHash* pProps); + virtual XnStatus Free(); + +private: + // helpers + XnShiftToDepthStreamHelper* m_pS2DHelper; +}; + +#endif //__XN_STREAM_READER_STREAM_HOLDER_H__ diff --git a/Source/XnDDK/XnStreamWriterDevice.cpp b/Source/XnDDK/XnStreamWriterDevice.cpp index 6bfa1c8..f01a8f8 100644 --- a/Source/XnDDK/XnStreamWriterDevice.cpp +++ b/Source/XnDDK/XnStreamWriterDevice.cpp @@ -1,344 +1,344 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamWriterDevice.h" -#include "XnStreamWriterStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamWriterDevice::XnStreamWriterDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : - XnStreamDevice(strName, nInternalBufferSize) -{ -} - -XnStreamWriterDevice::~XnStreamWriterDevice() -{ -} - -XnStatus XnStreamWriterDevice::InitImpl(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first init self - nRetVal = XnDeviceBase::InitImpl(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = InitPacker(pDeviceConfig->cpConnectionString); - XN_IS_STATUS_OK(nRetVal); - - // now take initial state - XnPropertySet* pSet; - nRetVal = XnPropertySetCreate(&pSet); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetAllProperties(pSet); - - // and write it down to stream - if (nRetVal == XN_STATUS_OK) - { - nRetVal = GetDataPacker()->WritePropertySet(pSet); - } - - XnPropertySetDestroy(&pSet); - - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetDataPacker()->WriteEnd(); - XN_IS_STATUS_OK(nRetVal); - - XnStreamDevice::Destroy(); - - XnStreamDevice::Destroy(); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create the stream - nRetVal = XnDeviceBase::CreateStream(StreamType, StreamName, pInitialValues); - XN_IS_STATUS_OK(nRetVal); - - XnStreamDeviceStreamHolder* pStreamHolder; - nRetVal = FindStream(StreamName, &pStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - // now set default compression - nRetVal = pStreamHolder->GetStream()->SetProperty(XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)GetDefaultCompression(StreamType)); - XN_IS_STATUS_OK(nRetVal); - - // get a list of this stream properties - XnPropertySet* pStreamProps; - nRetVal = XnPropertySetCreate(&pStreamProps); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pStreamHolder->GetStream()->GetAllProperties(pStreamProps); - if (nRetVal != XN_STATUS_OK) - { - XnPropertySetDestroy(&pStreamProps); - return (nRetVal); - } - - // and write it to file - nRetVal = GetDataPacker()->WriteNewStream(StreamType, StreamName, pStreamProps); - if (nRetVal != XN_STATUS_OK) - { - XnPropertySetDestroy(&pStreamProps); - XnDeviceBase::DestroyStream(StreamName); - return (nRetVal); - } - - nRetVal = XnPropertySetDestroy(&pStreamProps); - if (nRetVal != XN_STATUS_OK) - { - XnDeviceBase::DestroyStream(StreamName); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::DestroyStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // destroy it - nRetVal = XnDeviceBase::DestroyStream(StreamName); - XN_IS_STATUS_OK(nRetVal); - - // write down that the stream was removed. - nRetVal = GetDataPacker()->WriteStreamRemoved(StreamName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::WriteStream(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutput); - - // find the stream - XnStreamDeviceStreamHolder* pStreamHolder; - nRetVal = FindStream(pStreamOutput->StreamName, &pStreamHolder); - XN_IS_STATUS_OK(nRetVal); - - if (!pStreamOutput->bIsNew) - { - // no need to write down the data - return XN_STATUS_OK; - } - - // write it to stream - nRetVal = XnDeviceBase::WriteStream(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - XnStreamWriterStream* pStream = (XnStreamWriterStream*)pStreamHolder->GetStream(); - - // and to file - nRetVal = pStream->GetDataPacker()->WriteStreamData(pStreamOutput, pStreamHolder->GetCodec()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnStreamWriterDevice::SortStreamOutputsByTimestamp(XnStreamData* apOutputs[], XnUInt32 nCount) -{ - // use bubble sort - XnUInt32 n = nCount; - XnBool bSwapped; - XnStreamData* pTemp; - - if (nCount == 0) - return; - - do - { - bSwapped = FALSE; - for (XnUInt32 i = 0; i < n - 1; ++i) - { - if (apOutputs[i]->nTimestamp > apOutputs[i+1]->nTimestamp) - { - // swap - pTemp = apOutputs[i]; - apOutputs[i] = apOutputs[i+1]; - apOutputs[i+1] = pTemp; - - bSwapped = TRUE; - } - } - - n -= 1; - - } while (bSwapped); -} - -XnStatus XnStreamWriterDevice::Write(XnStreamDataSet* pStreamOutputSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - - // get a list of objects in the set - XnStreamData* aOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, aOutputs, &nCount); - XN_IS_STATUS_OK(nRetVal); - - // sort them out by timestamp - SortStreamOutputsByTimestamp(aOutputs, nCount); - - // now write them one by one - for (XnUInt32 i = 0; i < nCount; ++i) - { - nRetVal = WriteStream(aOutputs[i]); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // this is just a writer device. It does what it's told (no checks) - nRetVal = pModule->UnsafeUpdateProperty(PropertyName, nValue); - XN_IS_STATUS_OK(nRetVal); - - GetDataPacker()->WriteProperty(ModuleName, PropertyName, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // this is just a writer device. It does what it's told (no checks) - nRetVal = pModule->UnsafeUpdateProperty(PropertyName, dValue); - XN_IS_STATUS_OK(nRetVal); - - GetDataPacker()->WriteProperty(ModuleName, PropertyName, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // this is just a writer device. It does what it's told (no checks) - nRetVal = pModule->UnsafeUpdateProperty(PropertyName, strValue); - XN_IS_STATUS_OK(nRetVal); - - GetDataPacker()->WriteProperty(ModuleName, PropertyName, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(ModuleName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - // this is just a writer device. It does what it's told (no checks) - nRetVal = pModule->UnsafeUpdateProperty(PropertyName, gbValue); - XN_IS_STATUS_OK(nRetVal); - - GetDataPacker()->WriteProperty(ModuleName, PropertyName, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterDevice::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamWriterStream* pStream; - XN_VALIDATE_NEW(pStream, XnStreamWriterStream, StreamType, StreamName, GetDataPacker()); - - XnStreamDeviceStreamHolder* pHolder = XN_NEW(XnStreamDeviceStreamHolder, pStream, FALSE); - if (pHolder == NULL) - { - XN_DELETE(pStream); - return XN_STATUS_ALLOC_FAILED; - } - - *ppStreamHolder = pHolder; - - return (XN_STATUS_OK); -} - -void XnStreamWriterDevice::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) -{ - XN_DELETE(pStreamHolder->GetModule()); - XN_DELETE(pStreamHolder); -} - -XnCompressionFormats XnStreamWriterDevice::GetDefaultCompression(const XnChar* strType) -{ - if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) - return XN_COMPRESSION_16Z_EMB_TABLE; - else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) - return XN_COMPRESSION_JPEG; - else - return XN_COMPRESSION_NONE; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamWriterDevice.h" +#include "XnStreamWriterStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamWriterDevice::XnStreamWriterDevice(const XnChar* strName, XnUInt32 nInternalBufferSize) : + XnStreamDevice(strName, nInternalBufferSize) +{ +} + +XnStreamWriterDevice::~XnStreamWriterDevice() +{ +} + +XnStatus XnStreamWriterDevice::InitImpl(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first init self + nRetVal = XnDeviceBase::InitImpl(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = InitPacker(pDeviceConfig->cpConnectionString); + XN_IS_STATUS_OK(nRetVal); + + // now take initial state + XnPropertySet* pSet; + nRetVal = XnPropertySetCreate(&pSet); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetAllProperties(pSet); + + // and write it down to stream + if (nRetVal == XN_STATUS_OK) + { + nRetVal = GetDataPacker()->WritePropertySet(pSet); + } + + XnPropertySetDestroy(&pSet); + + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetDataPacker()->WriteEnd(); + XN_IS_STATUS_OK(nRetVal); + + XnStreamDevice::Destroy(); + + XnStreamDevice::Destroy(); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // create the stream + nRetVal = XnDeviceBase::CreateStream(StreamType, StreamName, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + XnStreamDeviceStreamHolder* pStreamHolder; + nRetVal = FindStream(StreamName, &pStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + // now set default compression + nRetVal = pStreamHolder->GetStream()->SetProperty(XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)GetDefaultCompression(StreamType)); + XN_IS_STATUS_OK(nRetVal); + + // get a list of this stream properties + XnPropertySet* pStreamProps; + nRetVal = XnPropertySetCreate(&pStreamProps); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pStreamHolder->GetStream()->GetAllProperties(pStreamProps); + if (nRetVal != XN_STATUS_OK) + { + XnPropertySetDestroy(&pStreamProps); + return (nRetVal); + } + + // and write it to file + nRetVal = GetDataPacker()->WriteNewStream(StreamType, StreamName, pStreamProps); + if (nRetVal != XN_STATUS_OK) + { + XnPropertySetDestroy(&pStreamProps); + XnDeviceBase::DestroyStream(StreamName); + return (nRetVal); + } + + nRetVal = XnPropertySetDestroy(&pStreamProps); + if (nRetVal != XN_STATUS_OK) + { + XnDeviceBase::DestroyStream(StreamName); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::DestroyStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // destroy it + nRetVal = XnDeviceBase::DestroyStream(StreamName); + XN_IS_STATUS_OK(nRetVal); + + // write down that the stream was removed. + nRetVal = GetDataPacker()->WriteStreamRemoved(StreamName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::WriteStream(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutput); + + // find the stream + XnStreamDeviceStreamHolder* pStreamHolder; + nRetVal = FindStream(pStreamOutput->StreamName, &pStreamHolder); + XN_IS_STATUS_OK(nRetVal); + + if (!pStreamOutput->bIsNew) + { + // no need to write down the data + return XN_STATUS_OK; + } + + // write it to stream + nRetVal = XnDeviceBase::WriteStream(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + XnStreamWriterStream* pStream = (XnStreamWriterStream*)pStreamHolder->GetStream(); + + // and to file + nRetVal = pStream->GetDataPacker()->WriteStreamData(pStreamOutput, pStreamHolder->GetCodec()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnStreamWriterDevice::SortStreamOutputsByTimestamp(XnStreamData* apOutputs[], XnUInt32 nCount) +{ + // use bubble sort + XnUInt32 n = nCount; + XnBool bSwapped; + XnStreamData* pTemp; + + if (nCount == 0) + return; + + do + { + bSwapped = FALSE; + for (XnUInt32 i = 0; i < n - 1; ++i) + { + if (apOutputs[i]->nTimestamp > apOutputs[i+1]->nTimestamp) + { + // swap + pTemp = apOutputs[i]; + apOutputs[i] = apOutputs[i+1]; + apOutputs[i+1] = pTemp; + + bSwapped = TRUE; + } + } + + n -= 1; + + } while (bSwapped); +} + +XnStatus XnStreamWriterDevice::Write(XnStreamDataSet* pStreamOutputSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + + // get a list of objects in the set + XnStreamData* aOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, aOutputs, &nCount); + XN_IS_STATUS_OK(nRetVal); + + // sort them out by timestamp + SortStreamOutputsByTimestamp(aOutputs, nCount); + + // now write them one by one + for (XnUInt32 i = 0; i < nCount; ++i) + { + nRetVal = WriteStream(aOutputs[i]); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // this is just a writer device. It does what it's told (no checks) + nRetVal = pModule->UnsafeUpdateProperty(PropertyName, nValue); + XN_IS_STATUS_OK(nRetVal); + + GetDataPacker()->WriteProperty(ModuleName, PropertyName, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // this is just a writer device. It does what it's told (no checks) + nRetVal = pModule->UnsafeUpdateProperty(PropertyName, dValue); + XN_IS_STATUS_OK(nRetVal); + + GetDataPacker()->WriteProperty(ModuleName, PropertyName, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // this is just a writer device. It does what it's told (no checks) + nRetVal = pModule->UnsafeUpdateProperty(PropertyName, strValue); + XN_IS_STATUS_OK(nRetVal); + + GetDataPacker()->WriteProperty(ModuleName, PropertyName, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(ModuleName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + // this is just a writer device. It does what it's told (no checks) + nRetVal = pModule->UnsafeUpdateProperty(PropertyName, gbValue); + XN_IS_STATUS_OK(nRetVal); + + GetDataPacker()->WriteProperty(ModuleName, PropertyName, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterDevice::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamWriterStream* pStream; + XN_VALIDATE_NEW(pStream, XnStreamWriterStream, StreamType, StreamName, GetDataPacker()); + + XnStreamDeviceStreamHolder* pHolder = XN_NEW(XnStreamDeviceStreamHolder, pStream, FALSE); + if (pHolder == NULL) + { + XN_DELETE(pStream); + return XN_STATUS_ALLOC_FAILED; + } + + *ppStreamHolder = pHolder; + + return (XN_STATUS_OK); +} + +void XnStreamWriterDevice::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) +{ + XN_DELETE(pStreamHolder->GetModule()); + XN_DELETE(pStreamHolder); +} + +XnCompressionFormats XnStreamWriterDevice::GetDefaultCompression(const XnChar* strType) +{ + if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) + return XN_COMPRESSION_16Z_EMB_TABLE; + else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) + return XN_COMPRESSION_JPEG; + else + return XN_COMPRESSION_NONE; +} diff --git a/Source/XnDDK/XnStreamWriterDevice.h b/Source/XnDDK/XnStreamWriterDevice.h index 2bd6f17..28c9826 100644 --- a/Source/XnDDK/XnStreamWriterDevice.h +++ b/Source/XnDDK/XnStreamWriterDevice.h @@ -1,72 +1,72 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_WRITER_DEVICE_H__ -#define __XN_STREAM_WRITER_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamDevice.h" -#include -#include "XnDataPacker.h" -#include -#include "XnStreamDeviceStreamHolder.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamWriterDevice : public XnStreamDevice -{ -public: - XnStreamWriterDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); - ~XnStreamWriterDevice(); - - XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - XnStatus Destroy(); - - XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); - XnStatus DestroyStream(const XnChar* StreamName); - - XnStatus Write(XnStreamDataSet* pStreamOutputSet); - XnStatus WriteStream(XnStreamData* pStreamOutput); - - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); - -protected: - XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppModuleHolder); - void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); - - virtual XnCompressionFormats GetDefaultCompression(const XnChar* strType); - -private: - void SortStreamOutputsByTimestamp(XnStreamData* apOutputs[], XnUInt32 nCount); -}; - -#endif //__XN_STREAM_WRITER_DEVICE_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_WRITER_DEVICE_H__ +#define __XN_STREAM_WRITER_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamDevice.h" +#include +#include "XnDataPacker.h" +#include +#include "XnStreamDeviceStreamHolder.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamWriterDevice : public XnStreamDevice +{ +public: + XnStreamWriterDevice(const XnChar* strName, XnUInt32 nInternalBufferSize); + ~XnStreamWriterDevice(); + + XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + XnStatus Destroy(); + + XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); + XnStatus DestroyStream(const XnChar* StreamName); + + XnStatus Write(XnStreamDataSet* pStreamOutputSet); + XnStatus WriteStream(XnStreamData* pStreamOutput); + + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* csValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); + +protected: + XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppModuleHolder); + void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); + + virtual XnCompressionFormats GetDefaultCompression(const XnChar* strType); + +private: + void SortStreamOutputsByTimestamp(XnStreamData* apOutputs[], XnUInt32 nCount); +}; + +#endif //__XN_STREAM_WRITER_DEVICE_H__ diff --git a/Source/XnDDK/XnStreamWriterStream.cpp b/Source/XnDDK/XnStreamWriterStream.cpp index 2490775..b4bcddb 100644 --- a/Source/XnDDK/XnStreamWriterStream.cpp +++ b/Source/XnDDK/XnStreamWriterStream.cpp @@ -1,57 +1,57 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamWriterStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamWriterStream::XnStreamWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker) : - XnDeviceStream(strType, strName), - m_pDataPacker(pDataPacker), - m_nFrameID(0) -{} - -XnStreamWriterStream::~XnStreamWriterStream() -{} - -XnStatus XnStreamWriterStream::WriteImpl(XnStreamData* pStreamData) -{ - m_nFrameID++; - pStreamData->nFrameID = m_nFrameID; - return (XN_STATUS_OK); -} - -XnStatus XnStreamWriterStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const -{ - // we use the same size we have now - *pnRequiredSize = GetRequiredDataSize(); - return XN_STATUS_OK; +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamWriterStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamWriterStream::XnStreamWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker) : + XnDeviceStream(strType, strName), + m_pDataPacker(pDataPacker), + m_nFrameID(0) +{} + +XnStreamWriterStream::~XnStreamWriterStream() +{} + +XnStatus XnStreamWriterStream::WriteImpl(XnStreamData* pStreamData) +{ + m_nFrameID++; + pStreamData->nFrameID = m_nFrameID; + return (XN_STATUS_OK); +} + +XnStatus XnStreamWriterStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const +{ + // we use the same size we have now + *pnRequiredSize = GetRequiredDataSize(); + return XN_STATUS_OK; } \ No newline at end of file diff --git a/Source/XnDDK/XnStreamWriterStream.h b/Source/XnDDK/XnStreamWriterStream.h index 4c0c5fd..4a81d39 100644 --- a/Source/XnDDK/XnStreamWriterStream.h +++ b/Source/XnDDK/XnStreamWriterStream.h @@ -1,60 +1,60 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_WRITER_STREAM_H__ -#define __XN_STREAM_WRITER_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceStream.h" -#include "XnDataPacker.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_DDK_CPP_API XnStreamWriterStream : public XnDeviceStream -{ -public: - XnStreamWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker); - ~XnStreamWriterStream(); - - inline XnUInt32 GetFrameID() { return m_nFrameID; } - inline XnDataPacker* GetDataPacker() { return m_pDataPacker; } - -protected: - XnStatus WriteImpl(XnStreamData* pStreamData); - XnStatus ReadImpl(XnStreamData* pStreamOutput) { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } - XnStatus Mirror(XnStreamData* pStreamData) const { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } - - XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; - -private: - XnUInt32 m_nFrameID; - XnDataPacker* m_pDataPacker; -}; - -#endif //__XN_STREAM_WRITER_STREAM_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_WRITER_STREAM_H__ +#define __XN_STREAM_WRITER_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceStream.h" +#include "XnDataPacker.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_DDK_CPP_API XnStreamWriterStream : public XnDeviceStream +{ +public: + XnStreamWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker); + ~XnStreamWriterStream(); + + inline XnUInt32 GetFrameID() { return m_nFrameID; } + inline XnDataPacker* GetDataPacker() { return m_pDataPacker; } + +protected: + XnStatus WriteImpl(XnStreamData* pStreamData); + XnStatus ReadImpl(XnStreamData* pStreamOutput) { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } + XnStatus Mirror(XnStreamData* pStreamData) const { return XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED; } + + XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; + +private: + XnUInt32 m_nFrameID; + XnDataPacker* m_pDataPacker; +}; + +#endif //__XN_STREAM_WRITER_STREAM_H__ diff --git a/Source/XnDDK/XnStreamingStream.cpp b/Source/XnDDK/XnStreamingStream.cpp index e7d8fd2..a463a7b 100644 --- a/Source/XnDDK/XnStreamingStream.cpp +++ b/Source/XnDDK/XnStreamingStream.cpp @@ -1,73 +1,73 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamingStream.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamingStream::XnStreamingStream(const XnChar* csType, const XnChar* csName) : - XnDeviceStream(csType, csName), - m_IsStreamingStream(XN_STREAM_PROPERTY_IS_STREAMING, TRUE), - m_ReadChunkSize(XN_STREAM_PROPERTY_READ_CHUNK_SIZE) -{ -} - -XnStatus XnStreamingStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnDeviceStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - m_ReadChunkSize.UpdateSetCallback(SetReadChunkSizeCallback, this); - - XN_VALIDATE_ADD_PROPERTIES(this, &m_IsStreamingStream, &m_ReadChunkSize); - - return (XN_STATUS_OK); -} - -XnStatus XnStreamingStream::SetReadChunkSize(XnUInt32 nChunkSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_ReadChunkSize.UnsafeUpdateValue(nChunkSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnStreamingStream::SetReadChunkSizeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnStreamingStream* pStream = (XnStreamingStream*)pCookie; - return pStream->SetReadChunkSize((XnUInt32)nValue); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamingStream.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamingStream::XnStreamingStream(const XnChar* csType, const XnChar* csName) : + XnDeviceStream(csType, csName), + m_IsStreamingStream(XN_STREAM_PROPERTY_IS_STREAMING, TRUE), + m_ReadChunkSize(XN_STREAM_PROPERTY_READ_CHUNK_SIZE) +{ +} + +XnStatus XnStreamingStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnDeviceStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + m_ReadChunkSize.UpdateSetCallback(SetReadChunkSizeCallback, this); + + XN_VALIDATE_ADD_PROPERTIES(this, &m_IsStreamingStream, &m_ReadChunkSize); + + return (XN_STATUS_OK); +} + +XnStatus XnStreamingStream::SetReadChunkSize(XnUInt32 nChunkSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_ReadChunkSize.UnsafeUpdateValue(nChunkSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnStreamingStream::SetReadChunkSizeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnStreamingStream* pStream = (XnStreamingStream*)pCookie; + return pStream->SetReadChunkSize((XnUInt32)nValue); +} diff --git a/Source/XnDDK/XnStreamingStream.h b/Source/XnDDK/XnStreamingStream.h index fc5c7ab..f5968dd 100644 --- a/Source/XnDDK/XnStreamingStream.h +++ b/Source/XnDDK/XnStreamingStream.h @@ -1,77 +1,77 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAMING_STREAM_H__ -#define __XN_STREAMING_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** Represents a base class for streams which are not frame based, by streaming. */ -class XN_DDK_CPP_API XnStreamingStream : public XnDeviceStream -{ -public: - XnStreamingStream(const XnChar* csType, const XnChar* csName); - ~XnStreamingStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Properties Getters - //--------------------------------------------------------------------------- - inline XnActualIntProperty& ReadChunkSizeProperty() { return m_ReadChunkSize; } - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - inline XnUInt32 GetReadChunkSize() { return (XnUInt32)m_ReadChunkSize.GetValue(); } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - virtual XnStatus SetReadChunkSize(XnUInt32 nChunkSize); - -private: - static XnStatus XN_CALLBACK_TYPE SetReadChunkSizeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_IsStreamingStream; - XnActualIntProperty m_ReadChunkSize; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAMING_STREAM_H__ +#define __XN_STREAMING_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** Represents a base class for streams which are not frame based, by streaming. */ +class XN_DDK_CPP_API XnStreamingStream : public XnDeviceStream +{ +public: + XnStreamingStream(const XnChar* csType, const XnChar* csName); + ~XnStreamingStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Properties Getters + //--------------------------------------------------------------------------- + inline XnActualIntProperty& ReadChunkSizeProperty() { return m_ReadChunkSize; } + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + inline XnUInt32 GetReadChunkSize() { return (XnUInt32)m_ReadChunkSize.GetValue(); } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + virtual XnStatus SetReadChunkSize(XnUInt32 nChunkSize); + +private: + static XnStatus XN_CALLBACK_TYPE SetReadChunkSizeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_IsStreamingStream; + XnActualIntProperty m_ReadChunkSize; +}; + #endif //__XN_STREAMING_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDDK/XnStringProperty.cpp b/Source/XnDDK/XnStringProperty.cpp index da2722d..bc828d4 100644 --- a/Source/XnDDK/XnStringProperty.cpp +++ b/Source/XnDDK/XnStringProperty.cpp @@ -1,99 +1,99 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStringProperty.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStringProperty::XnStringProperty(const XnChar* strName, XnChar* pValueHolder, const XnChar* strModule /* = "" */) : - XnProperty(XN_PROPERTY_TYPE_STRING, pValueHolder, strName, strModule) -{ -} - -XnStatus XnStringProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar csValue[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = xnOSReadStringFromINI(csINIFile, csSection, GetName(), csValue, XN_DEVICE_MAX_STRING_LENGTH); - if (nRetVal == XN_STATUS_OK) - { - nRetVal = SetValue(csValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnStringProperty::CopyValueImpl(void* pDest, const void* pSource) const -{ - strncpy((char*)pDest, (const char*)pSource, XN_DEVICE_MAX_STRING_LENGTH); - return XN_STATUS_OK; -} - -XnBool XnStringProperty::IsEqual(const void* pValue1, const void* pValue2) const -{ - return (strncmp((const XnChar*)pValue1, (const XnChar*)pValue2, XN_DEVICE_MAX_STRING_LENGTH) == 0); -} - -XnStatus XnStringProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) -{ - SetFuncPtr pCallback = (SetFuncPtr)pFunc; - return pCallback(this, (const XnChar*)pValue, pCookie); -} - -XnStatus XnStringProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const -{ - GetFuncPtr pCallback = (GetFuncPtr)pFunc; - return pCallback(this, (XnChar*)pValue, pCookie); -} - -XnBool XnStringProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const -{ - strncpy(csValue, (const XnChar*)pValue, XN_DEVICE_MAX_STRING_LENGTH); - return TRUE; -} - -XnStatus XnStringProperty::AddToPropertySet(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = GetValue(strValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddStringProperty(pSet, GetModule(), GetName(), strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStringProperty.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStringProperty::XnStringProperty(const XnChar* strName, XnChar* pValueHolder, const XnChar* strModule /* = "" */) : + XnProperty(XN_PROPERTY_TYPE_STRING, pValueHolder, strName, strModule) +{ +} + +XnStatus XnStringProperty::ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar csValue[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = xnOSReadStringFromINI(csINIFile, csSection, GetName(), csValue, XN_DEVICE_MAX_STRING_LENGTH); + if (nRetVal == XN_STATUS_OK) + { + nRetVal = SetValue(csValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnStringProperty::CopyValueImpl(void* pDest, const void* pSource) const +{ + strncpy((char*)pDest, (const char*)pSource, XN_DEVICE_MAX_STRING_LENGTH); + return XN_STATUS_OK; +} + +XnBool XnStringProperty::IsEqual(const void* pValue1, const void* pValue2) const +{ + return (strncmp((const XnChar*)pValue1, (const XnChar*)pValue2, XN_DEVICE_MAX_STRING_LENGTH) == 0); +} + +XnStatus XnStringProperty::CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie) +{ + SetFuncPtr pCallback = (SetFuncPtr)pFunc; + return pCallback(this, (const XnChar*)pValue, pCookie); +} + +XnStatus XnStringProperty::CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const +{ + GetFuncPtr pCallback = (GetFuncPtr)pFunc; + return pCallback(this, (XnChar*)pValue, pCookie); +} + +XnBool XnStringProperty::ConvertValueToString(XnChar* csValue, const void* pValue) const +{ + strncpy(csValue, (const XnChar*)pValue, XN_DEVICE_MAX_STRING_LENGTH); + return TRUE; +} + +XnStatus XnStringProperty::AddToPropertySet(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = GetValue(strValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddStringProperty(pSet, GetModule(), GetName(), strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDDK/XnStringProperty.h b/Source/XnDDK/XnStringProperty.h index 49a58ff..8806197 100644 --- a/Source/XnDDK/XnStringProperty.h +++ b/Source/XnDDK/XnStringProperty.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STRING_PROPERTY_H__ -#define __XN_STRING_PROPERTY_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Class -//--------------------------------------------------------------------------- - -/** -* A property of type general. -*/ -class XN_DDK_CPP_API XnStringProperty : public XnProperty -{ -public: - XnStringProperty(const XnChar* strName, XnChar* pValueHolder, const XnChar* strModule = ""); - - typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnStringProperty* pSender, const XnChar* strValue, void* pCookie); - typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnStringProperty* pSender, XnChar* csValue, void* pCookie); - - inline XnStatus SetValue(const XnChar* strValue) - { - XN_VALIDATE_INPUT_PTR(strValue); - return XnProperty::SetValue(strValue); - } - - inline XnStatus GetValue(XnChar* csValue) const - { - XN_VALIDATE_INPUT_PTR(csValue); - return XnProperty::GetValue(csValue); - } - - inline XnStatus UnsafeUpdateValue(const XnChar* strValue) - { - XN_VALIDATE_INPUT_PTR(strValue); - return XnProperty::UnsafeUpdateValue(strValue); - } - - inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); - } - - inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) - { - XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); - } - - XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); - - XnStatus AddToPropertySet(XnPropertySet* pSet); - -protected: - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; - virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; - virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); - virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; - virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STRING_PROPERTY_H__ +#define __XN_STRING_PROPERTY_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Class +//--------------------------------------------------------------------------- + +/** +* A property of type general. +*/ +class XN_DDK_CPP_API XnStringProperty : public XnProperty +{ +public: + XnStringProperty(const XnChar* strName, XnChar* pValueHolder, const XnChar* strModule = ""); + + typedef XnStatus (XN_CALLBACK_TYPE* SetFuncPtr)(XnStringProperty* pSender, const XnChar* strValue, void* pCookie); + typedef XnStatus (XN_CALLBACK_TYPE* GetFuncPtr)(const XnStringProperty* pSender, XnChar* csValue, void* pCookie); + + inline XnStatus SetValue(const XnChar* strValue) + { + XN_VALIDATE_INPUT_PTR(strValue); + return XnProperty::SetValue(strValue); + } + + inline XnStatus GetValue(XnChar* csValue) const + { + XN_VALIDATE_INPUT_PTR(csValue); + return XnProperty::GetValue(csValue); + } + + inline XnStatus UnsafeUpdateValue(const XnChar* strValue) + { + XN_VALIDATE_INPUT_PTR(strValue); + return XnProperty::UnsafeUpdateValue(strValue); + } + + inline void UpdateSetCallback(SetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateSetCallback((XnProperty::SetFuncPtr)pFunc, pCookie); + } + + inline void UpdateGetCallback(GetFuncPtr pFunc, void* pCookie) + { + XnProperty::UpdateGetCallback((XnProperty::GetFuncPtr)pFunc, pCookie); + } + + XnStatus ReadValueFromFile(const XnChar* csINIFile, const XnChar* csSection); + + XnStatus AddToPropertySet(XnPropertySet* pSet); + +protected: + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + virtual XnStatus CopyValueImpl(void* pDest, const void* pSource) const; + virtual XnBool IsEqual(const void* pValue1, const void* pValue2) const; + virtual XnStatus CallSetCallback(XnProperty::SetFuncPtr pFunc, const void* pValue, void* pCookie); + virtual XnStatus CallGetCallback(XnProperty::GetFuncPtr pFunc, void* pValue, void* pCookie) const; + virtual XnBool ConvertValueToString(XnChar* csValue, const void* pValue) const; +}; + #endif //__XN_STRING_PROPERTY_H__ \ No newline at end of file diff --git a/Source/XnDeviceFile/CMakeLists.txt b/Source/XnDeviceFile/CMakeLists.txt new file mode 100644 index 0000000..9de2c0e --- /dev/null +++ b/Source/XnDeviceFile/CMakeLists.txt @@ -0,0 +1,46 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR} + ${XNCORE_INCLUDE_DIR} + ../ +) + +# Get sources +# ------------ +file(GLOB ${XNDEVICEFILE_LIB_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_library( + ${XNDEVICEFILE_LIB_NAME} + SHARED + ${${XNDEVICEFILE_LIB_NAME}_sources} +) + +target_link_libraries( + ${XNDEVICEFILE_LIB_NAME} + ${XNFORMAT_LIB_NAME} + ${XNDDK_LIB_NAME} +) + + +# The install_name is Mac OSX specific and is used to set the RPATH on a executable +# On Mac OSX the library can hold information for the rpath of the executable which +# uses the library. +# ---------------------------------------------------------------------------------- +if(SENSOR_PLATFORM_MAC) + set_target_properties(${XNDEVICEFILE_LIB_NAME} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR ${INSTALL_NAME_VALUE} + ) +endif() + + +# Set install dir +# --------------- +install( + TARGETS ${XNDEVICEFILE_LIB_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) + diff --git a/Source/XnDeviceFile/XnDeviceFile.cpp b/Source/XnDeviceFile/XnDeviceFile.cpp index 344d3be..9dcff39 100644 --- a/Source/XnDeviceFile/XnDeviceFile.cpp +++ b/Source/XnDeviceFile/XnDeviceFile.cpp @@ -1,114 +1,114 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnDeviceFile.h" -#include "XnDeviceFileReader.h" -#include "XnDeviceFileWriter.h" -#include - -#define XN_DEVICE_BASE_DERIVATIVE XnDeviceFile -#include - -XnStatus XnDeviceFile::GetDefinition(XnDeviceDefinition* pDeviceDefinition) -{ - XN_VALIDATE_OUTPUT_PTR(pDeviceDefinition); - - pDeviceDefinition->cpName = XN_DEVICE_NAME; - pDeviceDefinition->cpDescription = XN_DEVICE_DESCRIPTION; - pDeviceDefinition->nMajorVersion = XN_DEVICE_MAJORVERSION; - pDeviceDefinition->nMinorVersion = XN_DEVICE_MINORVERSION; - pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFile::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - XN_VALIDATE_INPUT_PTR(pnCount); - - *pnCount = 0; - - return (XN_STATUS_OK); -} - -XnDeviceFile::XnDeviceFile() : - XnDeviceBaseProxy(NULL) -{ -} - -XnDeviceFile::~XnDeviceFile() -{ - -} - -XnStatus XnDeviceFile::Init(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pDeviceConfig); - - XnDeviceBase* pActualDeviceFile = NULL; - - switch (pDeviceConfig->DeviceMode) - { - case XN_DEVICE_MODE_READ: - XN_VALIDATE_NEW(pActualDeviceFile, XnDeviceFileReader); - break; - case XN_DEVICE_MODE_WRITE: - XN_VALIDATE_NEW(pActualDeviceFile, XnDeviceFileWriter); - break; - default: - return XN_STATUS_IO_DEVICE_INVALID_MODE; - } - - // init actual device - nRetVal = pActualDeviceFile->Init(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - ReplaceActualDevice(pActualDeviceFile); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFile::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // destroy actual - nRetVal = XnDeviceBaseProxy::Destroy(); - XN_IS_STATUS_OK(nRetVal); - - ReplaceActualDevice(NULL); - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnDeviceFile.h" +#include "XnDeviceFileReader.h" +#include "XnDeviceFileWriter.h" +#include + +#define XN_DEVICE_BASE_DERIVATIVE XnDeviceFile +#include + +XnStatus XnDeviceFile::GetDefinition(XnDeviceDefinition* pDeviceDefinition) +{ + XN_VALIDATE_OUTPUT_PTR(pDeviceDefinition); + + pDeviceDefinition->cpName = XN_DEVICE_NAME; + pDeviceDefinition->cpDescription = XN_DEVICE_DESCRIPTION; + pDeviceDefinition->nMajorVersion = XN_DEVICE_MAJORVERSION; + pDeviceDefinition->nMinorVersion = XN_DEVICE_MINORVERSION; + pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFile::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + XN_VALIDATE_INPUT_PTR(pnCount); + + *pnCount = 0; + + return (XN_STATUS_OK); +} + +XnDeviceFile::XnDeviceFile() : + XnDeviceBaseProxy(NULL) +{ +} + +XnDeviceFile::~XnDeviceFile() +{ + +} + +XnStatus XnDeviceFile::Init(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pDeviceConfig); + + XnDeviceBase* pActualDeviceFile = NULL; + + switch (pDeviceConfig->DeviceMode) + { + case XN_DEVICE_MODE_READ: + XN_VALIDATE_NEW(pActualDeviceFile, XnDeviceFileReader); + break; + case XN_DEVICE_MODE_WRITE: + XN_VALIDATE_NEW(pActualDeviceFile, XnDeviceFileWriter); + break; + default: + return XN_STATUS_IO_DEVICE_INVALID_MODE; + } + + // init actual device + nRetVal = pActualDeviceFile->Init(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + ReplaceActualDevice(pActualDeviceFile); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFile::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // destroy actual + nRetVal = XnDeviceBaseProxy::Destroy(); + XN_IS_STATUS_OK(nRetVal); + + ReplaceActualDevice(NULL); + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDeviceFile/XnDeviceFile.h b/Source/XnDeviceFile/XnDeviceFile.h index a29e6bc..ada3e71 100644 --- a/Source/XnDeviceFile/XnDeviceFile.h +++ b/Source/XnDeviceFile/XnDeviceFile.h @@ -1,105 +1,105 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_DEVICEFILE_H_ -#define _XN_DEVICEFILE_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#ifndef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS - #undef XN_DEVICE_EXPORT_PREFIX - #define XN_DEVICE_EXPORT_PREFIX File_ -#endif - -#include -#include - -// #include -// #include -// #include -// #include -// #include -//#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEVICE_MAJORVERSION 1 -#define XN_DEVICE_MINORVERSION 0 -#define XN_DEVICE_NAME "File" -#define XN_DEVICE_DESCRIPTION "Xiron I/O File Device" - -#define XN_MASK_FILE "DeviceFile" - -#define XN_DEVICE_FILE_DEFAULT_DEPTH_COMP_FORMAT XN_STREAM_DEFAULT_DEPTH_COMPRESSION_FORMAT; -#define XN_DEVICE_FILE_DEFAULT_IMAGE_COMP_FORMAT XN_STREAM_DEFAULT_IMAGE_COMPRESSION_FORMAT; -#define XN_DEVICE_FILE_DEFAULT_MISC_COMP_FORMAT XN_STREAM_DEFAULT_MISC_COMPRESSION_FORMAT; -#define XN_DEVICE_FILE_DEFAULT_AUDIO_COMP_FORMAT XN_STREAM_DEFAULT_AUDIO_COMPRESSION_FORMAT; - -#define XN_DEVICE_FILE_MAX_INTERNAL_BUFFER (30 * 1024 * 1024) - -/** The length of the Xiron data packer string prefix. */ -#define XN_DEVICE_FILE_MAGIC_LEN 4 - -/** The string prefix of every Xiron stream. */ -#define XN_DEVICE_FILE_MAGIC_V1 "XS10" -#define XN_DEVICE_FILE_MAGIC_V2 "XS20" -#define XN_DEVICE_FILE_MAGIC_V3 "XS30" -#define XN_DEVICE_FILE_MAGIC_V4 "XS40" - -//--------------------------------------------------------------------------- -// Structures -//--------------------------------------------------------------------------- - -class XnDeviceFile : public XnDeviceBaseProxy -{ -public: - XnDeviceFile(); - ~XnDeviceFile(); - - static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); - static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); - - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus Destroy(); - - static XnStatus DestroyStreamData(XnStreamData** ppStreamData) - { - return XnDeviceBase::DestroyStreamData(ppStreamData); - } -}; - -typedef struct XnDepthCutOff -{ - XnBool bEnabled; - XnDepthPixel nMin; - XnDepthPixel nMax; -} XnDepthCutOff; - -#endif //_XN_DEVICEFILE_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_DEVICEFILE_H_ +#define _XN_DEVICEFILE_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#ifndef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS + #undef XN_DEVICE_EXPORT_PREFIX + #define XN_DEVICE_EXPORT_PREFIX File_ +#endif + +#include +#include + +// #include +// #include +// #include +// #include +// #include +//#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEVICE_MAJORVERSION 1 +#define XN_DEVICE_MINORVERSION 0 +#define XN_DEVICE_NAME "File" +#define XN_DEVICE_DESCRIPTION "Xiron I/O File Device" + +#define XN_MASK_FILE "DeviceFile" + +#define XN_DEVICE_FILE_DEFAULT_DEPTH_COMP_FORMAT XN_STREAM_DEFAULT_DEPTH_COMPRESSION_FORMAT; +#define XN_DEVICE_FILE_DEFAULT_IMAGE_COMP_FORMAT XN_STREAM_DEFAULT_IMAGE_COMPRESSION_FORMAT; +#define XN_DEVICE_FILE_DEFAULT_MISC_COMP_FORMAT XN_STREAM_DEFAULT_MISC_COMPRESSION_FORMAT; +#define XN_DEVICE_FILE_DEFAULT_AUDIO_COMP_FORMAT XN_STREAM_DEFAULT_AUDIO_COMPRESSION_FORMAT; + +#define XN_DEVICE_FILE_MAX_INTERNAL_BUFFER (30 * 1024 * 1024) + +/** The length of the Xiron data packer string prefix. */ +#define XN_DEVICE_FILE_MAGIC_LEN 4 + +/** The string prefix of every Xiron stream. */ +#define XN_DEVICE_FILE_MAGIC_V1 "XS10" +#define XN_DEVICE_FILE_MAGIC_V2 "XS20" +#define XN_DEVICE_FILE_MAGIC_V3 "XS30" +#define XN_DEVICE_FILE_MAGIC_V4 "XS40" + +//--------------------------------------------------------------------------- +// Structures +//--------------------------------------------------------------------------- + +class XnDeviceFile : public XnDeviceBaseProxy +{ +public: + XnDeviceFile(); + ~XnDeviceFile(); + + static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); + static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); + + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus Destroy(); + + static XnStatus DestroyStreamData(XnStreamData** ppStreamData) + { + return XnDeviceBase::DestroyStreamData(ppStreamData); + } +}; + +typedef struct XnDepthCutOff +{ + XnBool bEnabled; + XnDepthPixel nMin; + XnDepthPixel nMax; +} XnDepthCutOff; + +#endif //_XN_DEVICEFILE_H_ diff --git a/Source/XnDeviceFile/XnDeviceFileReader.cpp b/Source/XnDeviceFile/XnDeviceFileReader.cpp index b45e10b..e0d1eb8 100644 --- a/Source/XnDeviceFile/XnDeviceFileReader.cpp +++ b/Source/XnDeviceFile/XnDeviceFileReader.cpp @@ -1,811 +1,811 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceFileReader.h" -#include -#include "XnDeviceFile.h" -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnLastStreamData -{ - XnUInt32 nPosition; - XnUInt32 nFrameID; - XnUInt64 nTimestamp; -} XnLastStreamData; - -XN_DECLARE_STRINGS_HASH(XnLastStreamData, XnLastStreamDataHash); - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDeviceFileReader::XnDeviceFileReader() : - XnStreamReaderDevice(XN_DEVICE_NAME, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER), - m_FrameDelay(XN_MODULE_PROPERTY_FRAME_DELAY, FALSE), - m_pBCData(NULL), - m_nFileVersion(-1), - m_nReferenceTime(0), - m_nReferenceTimestamp(0), - m_bFileHasData(FALSE), - m_bStreamsCollectionChanged(FALSE), - m_pThis(this), - m_InstancePointer(XN_FILE_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL) -{ - m_FrameDelay.UpdateSetCallbackToDefault(); -} - -XnDeviceFileReader::~XnDeviceFileReader() -{ - -} - -XnStatus XnDeviceFileReader::InitImpl(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamReaderDevice::InitImpl(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - // register to events - nRetVal = OnStreamCollectionChangedEvent().Register(StreamCollectionChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - - // TODO: remove this - ReadWriteModeProperty().UnsafeUpdateValue(XN_DEVICE_MODE_READ); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamReaderDevice::CreateDeviceModule(ppModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); - - // add sensor properties - XnProperty* pProps[] = { &m_FrameDelay, &m_InstancePointer }; - - nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(*ppModuleHolder); - *ppModuleHolder = NULL; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // open file - XN_VALIDATE_NEW_AND_INIT(pStream, XnIOFileStream, strConnectionString, XN_OS_FILE_READ); - - // read version - nRetVal = ReadFileVersion(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pStream); - pStream = NULL; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -void XnDeviceFileReader::DestroyIOStreamImpl(XnIOStream* pStream) -{ - XN_DELETE(pStream); -} - -XnStatus XnDeviceFileReader::ReadFileVersion() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read magic from file - XnChar csFileMagic[XN_DEVICE_FILE_MAGIC_LEN]; - nRetVal = GetIOStream()->ReadData((XnUChar*)csFileMagic, XN_DEVICE_FILE_MAGIC_LEN); - XN_IS_STATUS_OK(nRetVal); - - if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V4, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 4; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V3, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 3; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V2, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 2; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V1, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 1; - } - else - { - XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "Invalid file magic!"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::ReadInitialState(XnPropertySet *pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_nFileVersion < 4) - { - if (m_pBCData == NULL) - { - nRetVal = BCInit(); - XN_IS_STATUS_OK(nRetVal); - } - - return BCReadInitialState(pSet); - } - - // first read first object - modules properties - using base - nRetVal = XnStreamReaderDevice::ReadInitialState(pSet); - XN_IS_STATUS_OK(nRetVal); - - // now continue reading until we get to first data - XnPackedDataType nType; - XnBool bStateEnd = FALSE; - XnUInt32 nPositionBefore; - - while (!bStateEnd) - { - nRetVal = GetIOStream()->Tell(&nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - switch (nType) - { - case XN_PACKED_NEW_STREAM: - { - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - XN_PROPERTY_SET_CREATE_ON_STACK(props); - nRetVal = GetDataPacker()->ReadNewStream(strType, strName, &props); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pStreamProps; - nRetVal = XnPropertySetDataDetachModule(props.pData, strName, &pStreamProps); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetDataAttachModule(pSet->pData, strName, pStreamProps); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_INT_PROPERTY: - { - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt64 nValue; - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &nValue); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModule, pModule); - XN_IS_STATUS_OK(nRetVal); - - XnProperty* pProp; - nRetVal = pModule->Get(strProp, pProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; - nRetVal = pIntProp->UnsafeUpdateValue(nValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_REAL_PROPERTY: - { - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnDouble dValue; - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &dValue); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModule, pModule); - XN_IS_STATUS_OK(nRetVal); - - XnProperty* pProp; - nRetVal = pModule->Get(strProp, pProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; - nRetVal = pRealProp->UnsafeUpdateValue(dValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_STRING_PROPERTY: - { - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModule, pModule); - XN_IS_STATUS_OK(nRetVal); - - XnProperty* pProp; - nRetVal = pModule->Get(strProp, pProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualStringProperty* pStringProp = (XnActualStringProperty*)pProp; - nRetVal = pStringProp->UnsafeUpdateValue(strValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_GENERAL_PROPERTY: - { - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnGeneralBuffer gbValue; - nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &gbValue); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pModule; - nRetVal = pSet->pData->Get(strModule, pModule); - XN_IS_STATUS_OK(nRetVal); - - XnProperty* pProp; - nRetVal = pModule->Get(strProp, pProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualGeneralProperty* pIntProp = (XnActualGeneralProperty*)pProp; - nRetVal = pIntProp->UnsafeUpdateValue(gbValue); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - // reached end of initial state. go back to beginning of this object - nRetVal = GetIOStream()->Seek(nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - // stop reading - bStateEnd = TRUE; - } - } // objects loop - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::HandleStreamRemoved(const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check for specific case: all streams are removed and then end-of-file is reached. - // in this case, we don't really want to destroy streams, just wrap around. - XnStringsHash StreamsToRemove; - nRetVal = StreamsToRemove.Set(strName, NULL); - XN_IS_STATUS_OK(nRetVal); - - XnPackedDataType nType = XN_PACKED_STREAM_REMOVED; - XnUInt32 nPositionBefore; - - while (TRUE) - { - nRetVal = GetIOStream()->Tell(&nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_STREAM_REMOVED) - { - XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = GetDataPacker()->ReadStreamRemoved(strTempName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = StreamsToRemove.Set(strTempName, NULL); - XN_IS_STATUS_OK(nRetVal); - } - else - { - break; - } - } - - if (nType != XN_PACKED_END) - { - // Not the case we were looking for. Remove those streams. - for (XnStringsHash::Iterator it = StreamsToRemove.begin(); it != StreamsToRemove.end(); ++it) - { - nRetVal = XnStreamReaderDevice::HandleStreamRemoved(it.Key()); - XN_IS_STATUS_OK(nRetVal); - } - } - - // in any case, the last object we read wasn't handled yet (end-of-stream or another event), so - // seek back, so it will be handled. - nRetVal = GetIOStream()->Seek(nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // ignore some properties - if ((strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_READ_WRITE_MODE) == 0) || - (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) || - (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_FRAME_DELAY) == 0) || - (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_DEVICE_NAME) == 0)) - { - return (XN_STATUS_OK); - } - else - { - nRetVal = XnStreamReaderDevice::HandleIntProperty(strModule, strName, nValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nPosition; - nRetVal = GetIOStream()->Tell(&nPosition); - XN_IS_STATUS_OK(nRetVal); - - XnUIntHash::Iterator it = m_PositionsToIgnore.end(); - if (XN_STATUS_OK == m_PositionsToIgnore.Find(nPosition, it)) - { - // ignore this one. Just update the frame ID - XnStreamDeviceStreamHolder* pHolder; - nRetVal = FindStream(pDataProps->StreamName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pHolder->GetStream(); - pStream->NewDataAvailable(); - - // and remove it from list - nRetVal = m_PositionsToIgnore.Remove(it); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // normal case. handle it - nRetVal = XnStreamReaderDevice::HandleStreamData(pDataProps, nCompression, nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::Rewind() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // go back to start of stream - nRetVal = GetIOStream()->Seek(XN_DEVICE_FILE_MAGIC_LEN); - XN_IS_STATUS_OK(nRetVal); - - // read initial state - XN_PROPERTY_SET_CREATE_ON_STACK(state); - nRetVal = ReadInitialState(&state); - XN_IS_STATUS_OK(nRetVal); - - // first handle current streams. remove or reset them - XnDeviceModuleHolderList streams; - nRetVal = GetStreamsList(streams); - XN_IS_STATUS_OK(nRetVal); - - for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) - { - XnDeviceModuleHolder* pHolder = *it; - - if (m_bStreamsCollectionChanged) - { - // we need to destroy all streams, and recreate them later - nRetVal = DestroyStream(pHolder->GetModule()->GetName()); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // just reset frame ID - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pHolder->GetModule(); - pStream->Reset(); - } - } - - // if we need, recreate streams - if (m_bStreamsCollectionChanged) - { - nRetVal = CreateStreams(&state); - XN_IS_STATUS_OK(nRetVal); - } - - // now set state. - for (XnPropertySetData::Iterator it = state.pData->begin(); it != state.pData->end(); ++it) - { - const XnChar* strName = it.Key(); - XnActualPropertiesHash* pHash = it.Value(); - - // fix it first - if (strcmp(strName, XN_MODULE_NAME_DEVICE) == 0) - { - pHash->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); - pHash->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); - } - - XnDeviceModule* pModule; - nRetVal = FindModule(strName, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->UnsafeBatchConfig(*pHash); - XN_IS_STATUS_OK(nRetVal); - } - - ResetLastTimestampAndFrame(); - m_nReferenceTimestamp = 0; - m_nReferenceTime = 0; - m_bStreamsCollectionChanged = FALSE; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::HandleEndOfStream() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bFileHasData) - { - XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "File does not contain any data..."); - } - - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnDeviceFileReader::FrameDelay(XnUInt64 nTimestamp) -{ - if (m_FrameDelay.GetValue() != TRUE) - return; - - if (!IsHighResTimestamps()) - nTimestamp *= 1000; - - // first time - if (m_nReferenceTime == 0) - { - xnOSQueryTimer(m_FrameDelayTimer, &m_nReferenceTime); - m_nReferenceTimestamp = nTimestamp; - return; - } - - // delay - XnUInt64 nNow; - xnOSQueryTimer(m_FrameDelayTimer, &nNow); - - // check how much time has passed in the stream - XnUInt64 nStreamDiff; - if (nTimestamp < m_nReferenceTimestamp) - { - nStreamDiff = 0; - } - else - { - nStreamDiff = nTimestamp - m_nReferenceTimestamp; - } - - // check how much time passed (for user) - XnUInt64 nClockDiff = nNow - m_nReferenceTime; - - // update reference (so that frame delay will work with Pause / Resume) - m_nReferenceTime = nNow; - m_nReferenceTimestamp = nTimestamp; - - // check if we need to wait - if (nClockDiff < nStreamDiff) - { - xnOSSleep(XnUInt32((nStreamDiff - nClockDiff) / 1000)); - - // take this time as a reference - xnOSQueryTimer(m_FrameDelayTimer, &m_nReferenceTime); - } -} - -XnStatus XnDeviceFileReader::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read until primary stream advanced - while (!HasPrimaryStreamAdvanced(pSet)) - { - XnBool bWrap; - nRetVal = ReadTillNextData(&bWrap); - XN_IS_STATUS_OK(nRetVal); - } - - FrameDelay(GetLastTimestamp()); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // play forward until we have new data in this stream - while (!pStream->IsNewDataAvailable()) - { - XnBool bWrap; - nRetVal = ReadTillNextData(&bWrap); - XN_IS_STATUS_OK(nRetVal); - } - - FrameDelay(pStream->GetLastTimestamp()); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::ReadTillNextData(XnBool* pbWrapOccurred) -{ - XnStatus nRetVal = XN_STATUS_OK; - - *pbWrapOccurred = FALSE; - - if (m_nFileVersion < 4) - { - nRetVal = BCReadFrame(pbWrapOccurred); - XN_IS_STATUS_OK(nRetVal); - } - else - { - XnPackedDataType nType = XN_PACKED_END; - while (nType != XN_PACKED_STREAM_DATA) - { - nRetVal = ReadNextEventFromStream(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_END) - { - *pbWrapOccurred = TRUE; - } - } - - m_bFileHasData = TRUE; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::SeekTo(XnUInt64 nMinTimestamp, XnUInt32 nMinFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first check if we need to seek forward or backwards (even if we're in the correct location, - // we need to rewind, so that next read will return this frame again). - if ((nMinTimestamp != 0 && nMinTimestamp <= GetLastTimestamp()) || - (nMinFrameID != 0 && nMinFrameID <= GetLastFrameID())) - { - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - } - - XnBool bFoundNewData = FALSE; - - // Keep current position. - XnUInt32 nStartingPosition; - nRetVal = GetIOStream()->Tell(&nStartingPosition); - XN_IS_STATUS_OK(nRetVal); - - // Take primary stream (it determines frame ID and timestamp) - XnPackedDataType nType = (XnPackedDataType)-1; - const XnChar* strPrimaryStream = GetPrimaryStream(); - if (strcmp(strPrimaryStream, XN_PRIMARY_STREAM_ANY) == 0 || - strcmp(strPrimaryStream, XN_PRIMARY_STREAM_NONE) == 0) - { - strPrimaryStream = NULL; - } - - // start seeking forward until point is reached. - XnUInt32 nFoundPosition; - XnLastStreamDataHash StreamsHash; - - while (TRUE) - { - XnUInt32 nPositionBefore; - nRetVal = GetIOStream()->Tell(&nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - XnUInt32 nPositionAfter; - nRetVal = GetIOStream()->Tell(&nPositionAfter); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_STREAM_DATA) - { - bFoundNewData = TRUE; - - XnStreamData props; - XnCompressionFormats nCompression; - XnUInt32 nCompressedSize; - nRetVal = GetDataPacker()->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - XnLastStreamData data; - if (XN_STATUS_OK != StreamsHash.Get(props.StreamName, data)) - { - XnStreamDeviceStreamHolder* pHolder; - nRetVal = FindStream(props.StreamName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - data.nFrameID = pHolder->GetStream()->GetLastFrameID() + 1; - } - else - { - // if we had previous data from this stream, ignore it - m_PositionsToIgnore.Set(data.nPosition, 0); - - ++data.nFrameID; - } - - data.nPosition = nPositionAfter; - data.nTimestamp = props.nTimestamp; - nRetVal = StreamsHash.Set(props.StreamName, data); - XN_IS_STATUS_OK(nRetVal); - - // now check if condition is met - if (strPrimaryStream == NULL || - strcmp(strPrimaryStream, props.StreamName) == 0) - { - if (data.nFrameID >= nMinFrameID && data.nTimestamp >= nMinTimestamp) - { - // we have everything we need - // keep this position (we'll read up till here). - nFoundPosition = nPositionAfter; - break; - } - } - } - else if (nType == XN_PACKED_END) - { - // we'll read up to the last data of each stream - nFoundPosition = nPositionBefore; - break; - } - } - - // now seek back - nRetVal = GetIOStream()->Seek(nStartingPosition); - XN_IS_STATUS_OK(nRetVal); - - if (bFoundNewData) - { - // read everything up to position - XnUInt32 nPositionAfter = nStartingPosition; - - while (nPositionAfter < nFoundPosition) - { - nRetVal = ReadNextEventFromStream(&nType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetIOStream()->Tell(&nPositionAfter); - XN_IS_STATUS_OK(nRetVal); - } - } - else - { - // just remark the data as new (this is last frame, return it again to user) - XnDeviceModuleHolderList streams; - nRetVal = GetStreamsList(streams); - XN_IS_STATUS_OK(nRetVal); - - for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); - pStream->ReMarkDataAsNew(); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::Seek(XnUInt64 nTimestamp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogInfo(XN_MASK_FILE, "Seeking file to timestamp %llu...", nTimestamp); - - if (m_nFileVersion < 4) - { - return BCSeek(nTimestamp); - } - - nRetVal = SeekTo(nTimestamp, 0); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::SeekFrame(XnUInt32 nFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // don't allow seeking to frame 0 - nFrameID = XN_MAX(nFrameID, 1); - - xnLogInfo(XN_MASK_FILE, "Seeking file to frame %u...", nFrameID); - - if (m_nFileVersion < 4) - { - return BCSeekFrame(nFrameID); - } - - nRetVal = SeekTo(0, nFrameID); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType) -{ - m_bStreamsCollectionChanged = TRUE; - return XN_STATUS_OK; -} - -void XnDeviceFileReader::StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie) -{ - XnDeviceFileReader* pThis = (XnDeviceFileReader*)pCookie; - pThis->OnStreamCollectionChanged(StreamName, EventType); -} - -XnStatus XnDeviceFileReader::ReadNextData() -{ - XnBool bDummy; - return ReadTillNextData(&bDummy); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceFileReader.h" +#include +#include "XnDeviceFile.h" +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnLastStreamData +{ + XnUInt32 nPosition; + XnUInt32 nFrameID; + XnUInt64 nTimestamp; +} XnLastStreamData; + +XN_DECLARE_STRINGS_HASH(XnLastStreamData, XnLastStreamDataHash); + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDeviceFileReader::XnDeviceFileReader() : + XnStreamReaderDevice(XN_DEVICE_NAME, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER), + m_FrameDelay(XN_MODULE_PROPERTY_FRAME_DELAY, FALSE), + m_pBCData(NULL), + m_nFileVersion(-1), + m_nReferenceTime(0), + m_nReferenceTimestamp(0), + m_bFileHasData(FALSE), + m_bStreamsCollectionChanged(FALSE), + m_pThis(this), + m_InstancePointer(XN_FILE_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL) +{ + m_FrameDelay.UpdateSetCallbackToDefault(); +} + +XnDeviceFileReader::~XnDeviceFileReader() +{ + +} + +XnStatus XnDeviceFileReader::InitImpl(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamReaderDevice::InitImpl(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + // register to events + nRetVal = OnStreamCollectionChangedEvent().Register(StreamCollectionChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + + // TODO: remove this + ReadWriteModeProperty().UnsafeUpdateValue(XN_DEVICE_MODE_READ); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamReaderDevice::CreateDeviceModule(ppModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); + + // add sensor properties + XnProperty* pProps[] = { &m_FrameDelay, &m_InstancePointer }; + + nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(*ppModuleHolder); + *ppModuleHolder = NULL; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // open file + XN_VALIDATE_NEW_AND_INIT(pStream, XnIOFileStream, strConnectionString, XN_OS_FILE_READ); + + // read version + nRetVal = ReadFileVersion(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pStream); + pStream = NULL; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +void XnDeviceFileReader::DestroyIOStreamImpl(XnIOStream* pStream) +{ + XN_DELETE(pStream); +} + +XnStatus XnDeviceFileReader::ReadFileVersion() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read magic from file + XnChar csFileMagic[XN_DEVICE_FILE_MAGIC_LEN]; + nRetVal = GetIOStream()->ReadData((XnUChar*)csFileMagic, XN_DEVICE_FILE_MAGIC_LEN); + XN_IS_STATUS_OK(nRetVal); + + if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V4, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 4; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V3, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 3; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V2, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 2; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V1, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 1; + } + else + { + XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "Invalid file magic!"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::ReadInitialState(XnPropertySet *pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_nFileVersion < 4) + { + if (m_pBCData == NULL) + { + nRetVal = BCInit(); + XN_IS_STATUS_OK(nRetVal); + } + + return BCReadInitialState(pSet); + } + + // first read first object - modules properties - using base + nRetVal = XnStreamReaderDevice::ReadInitialState(pSet); + XN_IS_STATUS_OK(nRetVal); + + // now continue reading until we get to first data + XnPackedDataType nType; + XnBool bStateEnd = FALSE; + XnUInt32 nPositionBefore; + + while (!bStateEnd) + { + nRetVal = GetIOStream()->Tell(&nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + switch (nType) + { + case XN_PACKED_NEW_STREAM: + { + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + XN_PROPERTY_SET_CREATE_ON_STACK(props); + nRetVal = GetDataPacker()->ReadNewStream(strType, strName, &props); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pStreamProps; + nRetVal = XnPropertySetDataDetachModule(props.pData, strName, &pStreamProps); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetDataAttachModule(pSet->pData, strName, pStreamProps); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_INT_PROPERTY: + { + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt64 nValue; + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &nValue); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModule, pModule); + XN_IS_STATUS_OK(nRetVal); + + XnProperty* pProp; + nRetVal = pModule->Get(strProp, pProp); + XN_IS_STATUS_OK(nRetVal); + + XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; + nRetVal = pIntProp->UnsafeUpdateValue(nValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_REAL_PROPERTY: + { + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnDouble dValue; + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &dValue); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModule, pModule); + XN_IS_STATUS_OK(nRetVal); + + XnProperty* pProp; + nRetVal = pModule->Get(strProp, pProp); + XN_IS_STATUS_OK(nRetVal); + + XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; + nRetVal = pRealProp->UnsafeUpdateValue(dValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_STRING_PROPERTY: + { + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModule, pModule); + XN_IS_STATUS_OK(nRetVal); + + XnProperty* pProp; + nRetVal = pModule->Get(strProp, pProp); + XN_IS_STATUS_OK(nRetVal); + + XnActualStringProperty* pStringProp = (XnActualStringProperty*)pProp; + nRetVal = pStringProp->UnsafeUpdateValue(strValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_GENERAL_PROPERTY: + { + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnGeneralBuffer gbValue; + nRetVal = GetDataPacker()->ReadProperty(strModule, strProp, &gbValue); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pModule; + nRetVal = pSet->pData->Get(strModule, pModule); + XN_IS_STATUS_OK(nRetVal); + + XnProperty* pProp; + nRetVal = pModule->Get(strProp, pProp); + XN_IS_STATUS_OK(nRetVal); + + XnActualGeneralProperty* pIntProp = (XnActualGeneralProperty*)pProp; + nRetVal = pIntProp->UnsafeUpdateValue(gbValue); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + // reached end of initial state. go back to beginning of this object + nRetVal = GetIOStream()->Seek(nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + // stop reading + bStateEnd = TRUE; + } + } // objects loop + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::HandleStreamRemoved(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check for specific case: all streams are removed and then end-of-file is reached. + // in this case, we don't really want to destroy streams, just wrap around. + XnStringsHash StreamsToRemove; + nRetVal = StreamsToRemove.Set(strName, NULL); + XN_IS_STATUS_OK(nRetVal); + + XnPackedDataType nType = XN_PACKED_STREAM_REMOVED; + XnUInt32 nPositionBefore; + + while (TRUE) + { + nRetVal = GetIOStream()->Tell(&nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_STREAM_REMOVED) + { + XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = GetDataPacker()->ReadStreamRemoved(strTempName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = StreamsToRemove.Set(strTempName, NULL); + XN_IS_STATUS_OK(nRetVal); + } + else + { + break; + } + } + + if (nType != XN_PACKED_END) + { + // Not the case we were looking for. Remove those streams. + for (XnStringsHash::Iterator it = StreamsToRemove.begin(); it != StreamsToRemove.end(); ++it) + { + nRetVal = XnStreamReaderDevice::HandleStreamRemoved(it.Key()); + XN_IS_STATUS_OK(nRetVal); + } + } + + // in any case, the last object we read wasn't handled yet (end-of-stream or another event), so + // seek back, so it will be handled. + nRetVal = GetIOStream()->Seek(nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // ignore some properties + if ((strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_READ_WRITE_MODE) == 0) || + (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) || + (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_FRAME_DELAY) == 0) || + (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_DEVICE_NAME) == 0)) + { + return (XN_STATUS_OK); + } + else + { + nRetVal = XnStreamReaderDevice::HandleIntProperty(strModule, strName, nValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nPosition; + nRetVal = GetIOStream()->Tell(&nPosition); + XN_IS_STATUS_OK(nRetVal); + + XnUIntHash::Iterator it = m_PositionsToIgnore.end(); + if (XN_STATUS_OK == m_PositionsToIgnore.Find(nPosition, it)) + { + // ignore this one. Just update the frame ID + XnStreamDeviceStreamHolder* pHolder; + nRetVal = FindStream(pDataProps->StreamName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pHolder->GetStream(); + pStream->NewDataAvailable(pDataProps->nTimestamp, pDataProps->nFrameID); + + // and remove it from list + nRetVal = m_PositionsToIgnore.Remove(it); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // normal case. handle it + nRetVal = XnStreamReaderDevice::HandleStreamData(pDataProps, nCompression, nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::Rewind() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // go back to start of stream + nRetVal = GetIOStream()->Seek(XN_DEVICE_FILE_MAGIC_LEN); + XN_IS_STATUS_OK(nRetVal); + + // read initial state + XN_PROPERTY_SET_CREATE_ON_STACK(state); + nRetVal = ReadInitialState(&state); + XN_IS_STATUS_OK(nRetVal); + + // first handle current streams. remove or reset them + XnDeviceModuleHolderList streams; + nRetVal = GetStreamsList(streams); + XN_IS_STATUS_OK(nRetVal); + + for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) + { + XnDeviceModuleHolder* pHolder = *it; + + if (m_bStreamsCollectionChanged) + { + // we need to destroy all streams, and recreate them later + nRetVal = DestroyStream(pHolder->GetModule()->GetName()); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // just reset frame ID + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pHolder->GetModule(); + pStream->Reset(); + } + } + + // if we need, recreate streams + if (m_bStreamsCollectionChanged) + { + nRetVal = CreateStreams(&state); + XN_IS_STATUS_OK(nRetVal); + } + + // now set state. + for (XnPropertySetData::Iterator it = state.pData->begin(); it != state.pData->end(); ++it) + { + const XnChar* strName = it.Key(); + XnActualPropertiesHash* pHash = it.Value(); + + // fix it first + if (strcmp(strName, XN_MODULE_NAME_DEVICE) == 0) + { + pHash->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); + pHash->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); + } + + XnDeviceModule* pModule; + nRetVal = FindModule(strName, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->UnsafeBatchConfig(*pHash); + XN_IS_STATUS_OK(nRetVal); + } + + ResetLastTimestampAndFrame(); + m_nReferenceTimestamp = 0; + m_nReferenceTime = 0; + m_bStreamsCollectionChanged = FALSE; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::HandleEndOfStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bFileHasData) + { + XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "File does not contain any data..."); + } + + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnDeviceFileReader::FrameDelay(XnUInt64 nTimestamp) +{ + if (m_FrameDelay.GetValue() != TRUE) + return; + + if (!IsHighResTimestamps()) + nTimestamp *= 1000; + + // first time + if (m_nReferenceTime == 0) + { + xnOSQueryTimer(m_FrameDelayTimer, &m_nReferenceTime); + m_nReferenceTimestamp = nTimestamp; + return; + } + + // delay + XnUInt64 nNow; + xnOSQueryTimer(m_FrameDelayTimer, &nNow); + + // check how much time has passed in the stream + XnUInt64 nStreamDiff; + if (nTimestamp < m_nReferenceTimestamp) + { + nStreamDiff = 0; + } + else + { + nStreamDiff = nTimestamp - m_nReferenceTimestamp; + } + + // check how much time passed (for user) + XnUInt64 nClockDiff = nNow - m_nReferenceTime; + + // update reference (so that frame delay will work with Pause / Resume) + m_nReferenceTime = nNow; + m_nReferenceTimestamp = nTimestamp; + + // check if we need to wait + if (nClockDiff < nStreamDiff) + { + xnOSSleep(XnUInt32((nStreamDiff - nClockDiff) / 1000)); + + // take this time as a reference + xnOSQueryTimer(m_FrameDelayTimer, &m_nReferenceTime); + } +} + +XnStatus XnDeviceFileReader::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read until primary stream advanced + while (!HasPrimaryStreamAdvanced(pSet)) + { + XnBool bWrap; + nRetVal = ReadTillNextData(&bWrap); + XN_IS_STATUS_OK(nRetVal); + } + + FrameDelay(GetLastTimestamp()); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // play forward until we have new data in this stream + while (!pStream->IsNewDataAvailable()) + { + XnBool bWrap; + nRetVal = ReadTillNextData(&bWrap); + XN_IS_STATUS_OK(nRetVal); + } + + FrameDelay(pStream->GetLastTimestamp()); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::ReadTillNextData(XnBool* pbWrapOccurred) +{ + XnStatus nRetVal = XN_STATUS_OK; + + *pbWrapOccurred = FALSE; + + if (m_nFileVersion < 4) + { + nRetVal = BCReadFrame(pbWrapOccurred); + XN_IS_STATUS_OK(nRetVal); + } + else + { + XnPackedDataType nType = XN_PACKED_END; + while (nType != XN_PACKED_STREAM_DATA) + { + nRetVal = ReadNextEventFromStream(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_END) + { + *pbWrapOccurred = TRUE; + } + } + + m_bFileHasData = TRUE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::SeekTo(XnUInt64 nMinTimestamp, XnUInt32 nMinFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first check if we need to seek forward or backwards (even if we're in the correct location, + // we need to rewind, so that next read will return this frame again). + if ((nMinTimestamp != 0 && nMinTimestamp <= GetLastTimestamp()) || + (nMinFrameID != 0 && nMinFrameID <= GetLastFrameID())) + { + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + } + + XnBool bFoundNewData = FALSE; + + // Keep current position. + XnUInt32 nStartingPosition; + nRetVal = GetIOStream()->Tell(&nStartingPosition); + XN_IS_STATUS_OK(nRetVal); + + // Take primary stream (it determines frame ID and timestamp) + XnPackedDataType nType = (XnPackedDataType)-1; + const XnChar* strPrimaryStream = GetPrimaryStream(); + if (strcmp(strPrimaryStream, XN_PRIMARY_STREAM_ANY) == 0 || + strcmp(strPrimaryStream, XN_PRIMARY_STREAM_NONE) == 0) + { + strPrimaryStream = NULL; + } + + // start seeking forward until point is reached. + XnUInt32 nFoundPosition; + XnLastStreamDataHash StreamsHash; + + while (TRUE) + { + XnUInt32 nPositionBefore; + nRetVal = GetIOStream()->Tell(&nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + XnUInt32 nPositionAfter; + nRetVal = GetIOStream()->Tell(&nPositionAfter); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_STREAM_DATA) + { + bFoundNewData = TRUE; + + XnStreamData props; + XnCompressionFormats nCompression; + XnUInt32 nCompressedSize; + nRetVal = GetDataPacker()->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + XnLastStreamData data; + if (XN_STATUS_OK != StreamsHash.Get(props.StreamName, data)) + { + XnStreamDeviceStreamHolder* pHolder; + nRetVal = FindStream(props.StreamName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + data.nFrameID = pHolder->GetStream()->GetLastFrameID() + 1; + } + else + { + // if we had previous data from this stream, ignore it + m_PositionsToIgnore.Set(data.nPosition, 0); + + ++data.nFrameID; + } + + data.nPosition = nPositionAfter; + data.nTimestamp = props.nTimestamp; + nRetVal = StreamsHash.Set(props.StreamName, data); + XN_IS_STATUS_OK(nRetVal); + + // now check if condition is met + if (strPrimaryStream == NULL || + strcmp(strPrimaryStream, props.StreamName) == 0) + { + if (data.nFrameID >= nMinFrameID && data.nTimestamp >= nMinTimestamp) + { + // we have everything we need + // keep this position (we'll read up till here). + nFoundPosition = nPositionAfter; + break; + } + } + } + else if (nType == XN_PACKED_END) + { + // we'll read up to the last data of each stream + nFoundPosition = nPositionBefore; + break; + } + } + + // now seek back + nRetVal = GetIOStream()->Seek(nStartingPosition); + XN_IS_STATUS_OK(nRetVal); + + if (bFoundNewData) + { + // read everything up to position + XnUInt32 nPositionAfter = nStartingPosition; + + while (nPositionAfter < nFoundPosition) + { + nRetVal = ReadNextEventFromStream(&nType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetIOStream()->Tell(&nPositionAfter); + XN_IS_STATUS_OK(nRetVal); + } + } + else + { + // just remark the data as new (this is last frame, return it again to user) + XnDeviceModuleHolderList streams; + nRetVal = GetStreamsList(streams); + XN_IS_STATUS_OK(nRetVal); + + for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); + pStream->ReMarkDataAsNew(); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::Seek(XnUInt64 nTimestamp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogInfo(XN_MASK_FILE, "Seeking file to timestamp %llu...", nTimestamp); + + if (m_nFileVersion < 4) + { + return BCSeek(nTimestamp); + } + + nRetVal = SeekTo(nTimestamp, 0); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::SeekFrame(XnUInt32 nFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // don't allow seeking to frame 0 + nFrameID = XN_MAX(nFrameID, 1); + + xnLogInfo(XN_MASK_FILE, "Seeking file to frame %u...", nFrameID); + + if (m_nFileVersion < 4) + { + return BCSeekFrame(nFrameID); + } + + nRetVal = SeekTo(0, nFrameID); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType) +{ + m_bStreamsCollectionChanged = TRUE; + return XN_STATUS_OK; +} + +void XnDeviceFileReader::StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie) +{ + XnDeviceFileReader* pThis = (XnDeviceFileReader*)pCookie; + pThis->OnStreamCollectionChanged(StreamName, EventType); +} + +XnStatus XnDeviceFileReader::ReadNextData() +{ + XnBool bDummy; + return ReadTillNextData(&bDummy); +} diff --git a/Source/XnDeviceFile/XnDeviceFileReader.h b/Source/XnDeviceFile/XnDeviceFileReader.h index 8080202..757bb1c 100644 --- a/Source/XnDeviceFile/XnDeviceFileReader.h +++ b/Source/XnDeviceFile/XnDeviceFileReader.h @@ -1,111 +1,111 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEVICE_FILE_READER_H__ -#define __XN_DEVICE_FILE_READER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceFile.h" -#include -#include -#include - -#define XN_FILE_PROPERTY_INSTANCE_POINTER "InstancePointer" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -struct XnFileBCData; -XN_DECLARE_DEFAULT_HASH(XnUInt32, XnValue, XnUIntHash); - -class XnDeviceFileReader : public XnStreamReaderDevice -{ -public: - XnDeviceFileReader(); - ~XnDeviceFileReader(); - - XnStatus Seek(XnUInt64 nTimestamp); - XnStatus SeekFrame(XnUInt32 nFrameID); - - XnStatus ReadNextData(); - -protected: - XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - - virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); - virtual void DestroyIOStreamImpl(XnIOStream* pStream); - - virtual XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); - - virtual XnStatus ReadInitialState(XnPropertySet* pSet); - virtual XnStatus HandleStreamRemoved(const XnChar* strName); - virtual XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); - virtual XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); - virtual XnStatus HandleEndOfStream(); - - XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); - XnStatus WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream); - - inline XnIOFileStream* GetIOStream() { return (XnIOFileStream*)XnStreamReaderDevice::GetIOStream(); } - -private: - XnStatus Rewind(); - XnStatus ReadFileVersion(); - XnStatus ReadTillNextData(XnBool* pbWrapOccurred); - void FrameDelay(XnUInt64 nTimestamp); - XnStatus SeekTo(XnUInt64 nMinTimestamp, XnUInt32 nMinFrameID); - - XnStatus OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType); - - static void XN_CALLBACK_TYPE StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie); - - // Some BC functions - XnStatus BCSeek(XnUInt64 nTimestamp); - XnStatus BCSeekFrame(XnUInt32 nFrameID); - XnStatus BCInit(); - XnStatus BCCalculatePackedBufferSize(); - XnStatus BCReadInitialState(XnPropertySet* pSet); - XnStatus BCReadFrame(XnBool* pbRewind); - XnStatus BCDestroy(); - - XnBool m_bFileHasData; - XnBool m_bStreamsCollectionChanged; - XnUInt32 m_nFileVersion; - XnUInt64 m_nReferenceTime; - XnUInt64 m_nReferenceTimestamp; - XnOSTimer m_FrameDelayTimer; - XnActualIntProperty m_FrameDelay; - XnFileBCData* m_pBCData; - XnUIntHash m_PositionsToIgnore; - - XnDeviceFileReader* m_pThis; - XnActualGeneralProperty m_InstancePointer; -}; - -#endif //__XN_DEVICE_FILE_READER_H__ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEVICE_FILE_READER_H__ +#define __XN_DEVICE_FILE_READER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceFile.h" +#include +#include +#include + +#define XN_FILE_PROPERTY_INSTANCE_POINTER "InstancePointer" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +struct XnFileBCData; +XN_DECLARE_DEFAULT_HASH(XnUInt32, XnValue, XnUIntHash); + +class XnDeviceFileReader : public XnStreamReaderDevice +{ +public: + XnDeviceFileReader(); + ~XnDeviceFileReader(); + + XnStatus Seek(XnUInt64 nTimestamp); + XnStatus SeekFrame(XnUInt32 nFrameID); + + XnStatus ReadNextData(); + +protected: + XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + + virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); + virtual void DestroyIOStreamImpl(XnIOStream* pStream); + + virtual XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); + + virtual XnStatus ReadInitialState(XnPropertySet* pSet); + virtual XnStatus HandleStreamRemoved(const XnChar* strName); + virtual XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); + virtual XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); + virtual XnStatus HandleEndOfStream(); + + XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); + XnStatus WaitForStream(XN_EVENT_HANDLE hNewDataEvent, XnDeviceStream* pStream); + + inline XnIOFileStream* GetIOStream() { return (XnIOFileStream*)XnStreamReaderDevice::GetIOStream(); } + +private: + XnStatus Rewind(); + XnStatus ReadFileVersion(); + XnStatus ReadTillNextData(XnBool* pbWrapOccurred); + void FrameDelay(XnUInt64 nTimestamp); + XnStatus SeekTo(XnUInt64 nMinTimestamp, XnUInt32 nMinFrameID); + + XnStatus OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType); + + static void XN_CALLBACK_TYPE StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie); + + // Some BC functions + XnStatus BCSeek(XnUInt64 nTimestamp); + XnStatus BCSeekFrame(XnUInt32 nFrameID); + XnStatus BCInit(); + XnStatus BCCalculatePackedBufferSize(); + XnStatus BCReadInitialState(XnPropertySet* pSet); + XnStatus BCReadFrame(XnBool* pbRewind); + XnStatus BCDestroy(); + + XnBool m_bFileHasData; + XnBool m_bStreamsCollectionChanged; + XnUInt32 m_nFileVersion; + XnUInt64 m_nReferenceTime; + XnUInt64 m_nReferenceTimestamp; + XnOSTimer m_FrameDelayTimer; + XnActualIntProperty m_FrameDelay; + XnFileBCData* m_pBCData; + XnUIntHash m_PositionsToIgnore; + + XnDeviceFileReader* m_pThis; + XnActualGeneralProperty m_InstancePointer; +}; + +#endif //__XN_DEVICE_FILE_READER_H__ + diff --git a/Source/XnDeviceFile/XnDeviceFileReaderBC.cpp b/Source/XnDeviceFile/XnDeviceFileReaderBC.cpp index 59609a1..ba7767b 100644 --- a/Source/XnDeviceFile/XnDeviceFileReaderBC.cpp +++ b/Source/XnDeviceFile/XnDeviceFileReaderBC.cpp @@ -1,1158 +1,1158 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceFileReader.h" -#include "XnDeviceFileReaderBC.h" -//#include "XnFileReaderStreamHelper.h" -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnStatus XnIOAdjustStreamPropertiesV3(const XnStreamProperties* pStreamPropertiesV3, XnStreamProperties* pStreamProperties) -{ - pStreamProperties->nStreamFlags = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nStreamFlags); - pStreamProperties->nNumOfFrames = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nNumOfFrames); - pStreamProperties->nDepthFramesPerSecond = pStreamPropertiesV3->nDepthFramesPerSecond; - pStreamProperties->nImageFramesPerSecond = pStreamPropertiesV3->nImageFramesPerSecond; - pStreamProperties->DepthFormat = XnStreamDepthFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->DepthFormat))); - pStreamProperties->nDepthXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthXRes); - pStreamProperties->nDepthYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthYRes); - pStreamProperties->nDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nDepthBufferSize); - pStreamProperties->nDepthTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nDepthTypeBitSize); - pStreamProperties->nDepthMinValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthMinValue); - pStreamProperties->nDepthMaxValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthMaxValue); - pStreamProperties->nDepthNoSampleValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthNoSampleValue); - pStreamProperties->nDepthShadowValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthShadowValue); - pStreamProperties->ImageFormat = XnStreamImageFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->ImageFormat))); - pStreamProperties->nImageXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nImageXRes); - pStreamProperties->nImageYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nImageYRes); - pStreamProperties->nImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nImageBufferSize); - pStreamProperties->nImageTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nImageTypeBitSize); - pStreamProperties->MiscFormat = XnStreamMiscFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->MiscFormat))); - pStreamProperties->nMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nMiscBufferSize); - pStreamProperties->nMiscTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nMiscTypeBitSize); - pStreamProperties->nZeroPlaneDistance = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nZeroPlaneDistance); - pStreamProperties->fZeroPlanePixelSize = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV3->fZeroPlanePixelSize); - pStreamProperties->fEmitterDCmosDistance = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV3->fEmitterDCmosDistance); - pStreamProperties->Shift2DepthData.bShift2DepthData = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.bShift2DepthData); - pStreamProperties->Shift2DepthData.nConstShift = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nConstShift); - pStreamProperties->Shift2DepthData.nPixelSizeFactor = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nPixelSizeFactor); - pStreamProperties->Shift2DepthData.nMaxShiftValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nMaxShiftValue); - pStreamProperties->Shift2DepthData.nMaxDepthValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nMaxDepthValue); - pStreamProperties->Shift2DepthData.nParamCoeff = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nParamCoeff); - pStreamProperties->Shift2DepthData.nShiftScale = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nShiftScale); - pStreamProperties->AudioFormat = XnStreamAudioFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->AudioFormat))); - pStreamProperties->nAudioNumOfChannels = pStreamPropertiesV3->nAudioNumOfChannels; - pStreamProperties->nAudioSampleRate = XnSampleRate(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->nAudioSampleRate))); - pStreamProperties->nAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nAudioBufferSize); - pStreamProperties->AudioReadMode = pStreamPropertiesV3->AudioReadMode; - pStreamProperties->nAudioReadChunkSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nAudioReadChunkSize); - - return (XN_STATUS_OK); -} - -XnStatus XnIOAdjustStreamPropertiesV2 (const XnStreamPropertiesV2* pStreamPropertiesV2, XnStreamProperties* pStreamProperties) -{ - pStreamProperties->nStreamFlags = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nStreamFlags); - pStreamProperties->nNumOfFrames = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nNumOfFrames); - pStreamProperties->nDepthFramesPerSecond = pStreamPropertiesV2->nDepthFramesPerSecond; - pStreamProperties->nImageFramesPerSecond = pStreamPropertiesV2->nImageFramesPerSecond; - pStreamProperties->DepthFormat = XnStreamDepthFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->DepthFormat))); - pStreamProperties->nDepthXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthXRes); - pStreamProperties->nDepthYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthYRes); - pStreamProperties->nDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nDepthBufferSize); - pStreamProperties->nDepthTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nDepthTypeBitSize); - pStreamProperties->nDepthMinValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthMinValue); - pStreamProperties->nDepthMaxValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthMaxValue); - pStreamProperties->nDepthNoSampleValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthNoSampleValue); - pStreamProperties->nDepthShadowValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthShadowValue); - pStreamProperties->ImageFormat = XnStreamImageFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->ImageFormat))); - pStreamProperties->nImageXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nImageXRes); - pStreamProperties->nImageYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nImageYRes); - pStreamProperties->nImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nImageBufferSize); - pStreamProperties->nImageTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nImageTypeBitSize); - pStreamProperties->MiscFormat = XnStreamMiscFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->MiscFormat))); - pStreamProperties->nMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nMiscBufferSize); - pStreamProperties->nMiscTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nMiscTypeBitSize); - pStreamProperties->nZeroPlaneDistance = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nZeroPlaneDistance); - pStreamProperties->fZeroPlanePixelSize = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV2->fZeroPlanePixelSize); - pStreamProperties->fEmitterDCmosDistance = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV2->fEmitterDCmosDistance); - pStreamProperties->Shift2DepthData.bShift2DepthData = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.bShift2DepthData); - pStreamProperties->Shift2DepthData.nConstShift = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nConstShift); - pStreamProperties->Shift2DepthData.nPixelSizeFactor = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nPixelSizeFactor); - pStreamProperties->Shift2DepthData.nMaxShiftValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nMaxShiftValue); - pStreamProperties->Shift2DepthData.nMaxDepthValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nMaxDepthValue); - pStreamProperties->Shift2DepthData.nParamCoeff = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nParamCoeff); - pStreamProperties->Shift2DepthData.nShiftScale = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nShiftScale); - - // fix old bug: in versions 2.x (until 2.6) pixel size was written 2 when decimation was enabled - // where it should be 2 when decimation is disabled. We don't know if decimation was used or not, - // so we deduce it from the FPS and resolution. - // In this case, we need to fix the pixel size factor. - if (pStreamProperties->Shift2DepthData.nPixelSizeFactor == 2 && pStreamProperties->nDepthXRes == 320 && pStreamProperties->nDepthFramesPerSecond == 30) - pStreamProperties->Shift2DepthData.nPixelSizeFactor = 1; - - pStreamProperties->AudioFormat = XnStreamAudioFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(XN_AUDIO_FORMAT_DISABLED))); - pStreamProperties->nAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(0); - - return (XN_STATUS_OK); -} - -XnStatus XnIOAdjustStreamPropertiesV1 (const XnStreamPropertiesV1* pStreamPropertiesV1, XnStreamProperties* pStreamProperties) -{ - // adjust from V1 to V2 - XnStreamPropertiesV2 StreamPropertiesV2; - - StreamPropertiesV2.nStreamFlags = pStreamPropertiesV1->nStreamFlags; - StreamPropertiesV2.nNumOfFrames = pStreamPropertiesV1->nNumOfFrames; - StreamPropertiesV2.nDepthFramesPerSecond = pStreamPropertiesV1->nFramesPerSecond; - StreamPropertiesV2.nImageFramesPerSecond = pStreamPropertiesV1->nFramesPerSecond; - StreamPropertiesV2.DepthFormat = pStreamPropertiesV1->DepthFormat; - StreamPropertiesV2.nDepthXRes = pStreamPropertiesV1->nDepthXRes; - StreamPropertiesV2.nDepthYRes = pStreamPropertiesV1->nDepthYRes; - StreamPropertiesV2.nDepthBufferSize = pStreamPropertiesV1->nDepthBufferSize; - StreamPropertiesV2.nDepthTypeBitSize = pStreamPropertiesV1->nDepthTypeBitSize; - StreamPropertiesV2.nDepthMinValue = pStreamPropertiesV1->nDepthMinValue; - StreamPropertiesV2.nDepthMaxValue = pStreamPropertiesV1->nDepthMaxValue; - StreamPropertiesV2.nDepthNoSampleValue = pStreamPropertiesV1->nDepthNoSampleValue; - StreamPropertiesV2.nDepthShadowValue = pStreamPropertiesV1->nDepthShadowValue; - StreamPropertiesV2.ImageFormat = pStreamPropertiesV1->ImageFormat; - StreamPropertiesV2.nImageXRes = pStreamPropertiesV1->nImageXRes; - StreamPropertiesV2.nImageYRes = pStreamPropertiesV1->nImageYRes; - StreamPropertiesV2.nImageBufferSize = pStreamPropertiesV1->nImageBufferSize; - StreamPropertiesV2.nImageTypeBitSize = pStreamPropertiesV1->nImageTypeBitSize; - StreamPropertiesV2.MiscFormat = pStreamPropertiesV1->MiscFormat; - StreamPropertiesV2.nMiscBufferSize = pStreamPropertiesV1->nMiscBufferSize; - StreamPropertiesV2.nMiscTypeBitSize = pStreamPropertiesV1->nMiscTypeBitSize; - StreamPropertiesV2.nZeroPlaneDistance = pStreamPropertiesV1->nZeroPlaneDistance; - StreamPropertiesV2.fZeroPlanePixelSize = pStreamPropertiesV1->fZeroPlanePixelSize; - StreamPropertiesV2.fEmitterDCmosDistance = 11; - StreamPropertiesV2.Shift2DepthData.bShift2DepthData = false; - - // 1.4 Code: 1280/XRes. this is the factor, to be multiplied with 2. - StreamPropertiesV2.Shift2DepthData.nPixelSizeFactor = (1280/2)/StreamPropertiesV2.nDepthXRes; - - // and now adjust from V2 to current - return XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, pStreamProperties); -} - -XnStatus XnIOAdjustStreamFramePropertiesV3(const XnStreamFrameProperties* pStreamFramePropertiesV3, XnStreamFrameProperties* pStreamFrameProperties) -{ - pStreamFrameProperties->nDepthFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV3->nDepthFrameID); - pStreamFrameProperties->nImageFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV3->nImageFrameID); - pStreamFrameProperties->nDepthTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nDepthTimeStamp); - pStreamFrameProperties->nImageTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nImageTimeStamp); - pStreamFrameProperties->nAudioTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nAudioTimeStamp); - - return (XN_STATUS_OK); -} - -XnStatus XnIOAdjustStreamFramePropertiesV2 (const XnStreamFramePropertiesV2* pStreamFramePropertiesV2, XnStreamFrameProperties* pStreamFrameProperties) -{ - pStreamFrameProperties->nDepthFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV2->nDepthFrameID); - pStreamFrameProperties->nImageFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV2->nImageFrameID); - pStreamFrameProperties->nDepthTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV2->nDepthTimeStamp); - pStreamFrameProperties->nImageTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV2->nImageTimeStamp); - pStreamFrameProperties->nAudioTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(0); - - return (XN_STATUS_OK); -} - -XnStatus XnIOAdjustStreamFramePropertiesV1 (const XnStreamFramePropertiesV1* pStreamFramePropertiesV1, XnStreamFrameProperties* pStreamFrameProperties) -{ - // adjust to V2 - XnStreamFramePropertiesV2 StreamFramePropertiesV2; - - StreamFramePropertiesV2.nDepthFrameID = pStreamFramePropertiesV1->nFrameID; - StreamFramePropertiesV2.nImageFrameID = pStreamFramePropertiesV1->nFrameID; - StreamFramePropertiesV2.nDepthTimeStamp = pStreamFramePropertiesV1->nTimeStamp; - StreamFramePropertiesV2.nImageTimeStamp = pStreamFramePropertiesV1->nTimeStamp; - - // and now adjust from V2 to current - return XnIOAdjustStreamFramePropertiesV2(&StreamFramePropertiesV2, pStreamFrameProperties); -} - -XnStatus XnIOAdjustPackedStreamPropertiesV2 (const XnPackedStreamPropertiesV2* pPackedStreamPropertiesV2, XnPackedStreamProperties* pPackedStreamProperties) -{ - pPackedStreamProperties->StreamDepthCompressionFormat = XnStreamDepthCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamDepthCompressionFormat)); - pPackedStreamProperties->StreamImageCompressionFormat = XnStreamImageCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamImageCompressionFormat)); - pPackedStreamProperties->StreamMiscCompressionFormat = XnStreamMiscCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamMiscCompressionFormat)); - pPackedStreamProperties->StreamAudioCompressionFormat = XnStreamAudioCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(XN_COMPRESSED_AUDIO_FORMAT_SKIP)); - - return XN_STATUS_OK; -} - -XnStatus XnIOAdjustPackedStreamFrameHeaderV2 (const XnPackedStreamFrameHeaderV2* pPackedStreamFrameHeaderV2, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) -{ - pPackedStreamFrameHeader->nCompDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompDepthBufferSize); - pPackedStreamFrameHeader->nCompImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompImageBufferSize); - pPackedStreamFrameHeader->nCompMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompMiscBufferSize); - pPackedStreamFrameHeader->nCompAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(0); - - return XN_STATUS_OK; -} - -XnStatus XnIOAdjustPackedStreamPropertiesV1 (const XnPackedStreamPropertiesV1* pPackedStreamPropertiesV1, XnPackedStreamProperties* pPackedStreamProperties) -{ - // V1 and V2 are the same, so adjust from V2 to current - return XnIOAdjustPackedStreamPropertiesV2(pPackedStreamPropertiesV1, pPackedStreamProperties); -} - -XnStatus XnIOAdjustPackedStreamFrameHeaderV1 (const XnPackedStreamFrameHeaderV1* pPackedStreamFrameHeaderV1, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) -{ - // V1 and V2 are the same, so adjust from V2 to current - return XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamFrameHeaderV1, pPackedStreamFrameHeader); -} - -XnStatus XnIOAdjustPackedStreamPropertiesV3 (const XnPackedStreamProperties* pPackedStreamPropertiesV3, XnPackedStreamProperties* pPackedStreamProperties) -{ - pPackedStreamProperties->StreamDepthCompressionFormat = XnStreamDepthCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamDepthCompressionFormat)); - pPackedStreamProperties->StreamImageCompressionFormat = XnStreamImageCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamImageCompressionFormat)); - pPackedStreamProperties->StreamMiscCompressionFormat = XnStreamMiscCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamMiscCompressionFormat)); - pPackedStreamProperties->StreamAudioCompressionFormat = XnStreamAudioCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamAudioCompressionFormat)); - - return XN_STATUS_OK; -} - -XnStatus XnIOAdjustPackedStreamFrameHeaderV3 (const XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeaderV3, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) -{ - pPackedStreamFrameHeader->nCompDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompDepthBufferSize); - pPackedStreamFrameHeader->nCompImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompImageBufferSize); - pPackedStreamFrameHeader->nCompMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompMiscBufferSize); - pPackedStreamFrameHeader->nCompAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompAudioBufferSize); - - return XN_STATUS_OK; -} - -XnStatus XnDeviceFileReader::BCInit() -{ - XN_VALIDATE_CALLOC(m_pBCData, XnFileBCData, 1); - return XN_STATUS_OK; -} - -XnStatus BCSetDepthProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_DEPTH); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_DEPTH); - XN_IS_STATUS_OK(nRetVal); - - XnCropping cropping = {0}; - XnGeneralBuffer gbCropping = XN_PACK_GENERAL_BUFFER(cropping); - nRetVal = XnPropertySetAddGeneralProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CROPPING, &gbCropping); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); - XN_IS_STATUS_OK(nRetVal); - - // set output format - XnOutputFormats nOutputFormat; - nRetVal = XnBCDepthFormatToOutputFormat(pStreamProperties->DepthFormat, &nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - // set resolution - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_X_RES, (XnUInt64)pStreamProperties->nDepthXRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_Y_RES, (XnUInt64)pStreamProperties->nDepthYRes); - XN_IS_STATUS_OK(nRetVal); - - // set FPS - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_FPS, (XnUInt64)pStreamProperties->nDepthFramesPerSecond); - XN_IS_STATUS_OK(nRetVal); - - // set required-output-size - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, pStreamProperties->nDepthBufferSize); - XN_IS_STATUS_OK(nRetVal); - - // set bytes per pixel - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_BYTES_PER_PIXEL, pStreamProperties->nDepthTypeBitSize / 8); - XN_IS_STATUS_OK(nRetVal); - - // set cut-off - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_DEPTH, (XnUInt64)pStreamProperties->nDepthMaxValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MIN_DEPTH, (XnUInt64)pStreamProperties->nDepthMinValue); - XN_IS_STATUS_OK(nRetVal); - - // no-value and shadow-value - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_NO_SAMPLE, pStreamProperties->nDepthNoSampleValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHADOW, pStreamProperties->nDepthShadowValue); - XN_IS_STATUS_OK(nRetVal); - - // zero plane - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, pStreamProperties->nZeroPlaneDistance); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddRealProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, pStreamProperties->fZeroPlanePixelSize); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddRealProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, pStreamProperties->fEmitterDCmosDistance); - XN_IS_STATUS_OK(nRetVal); - - // shift-to-depth - if (pStreamProperties->Shift2DepthData.bShift2DepthData) - { - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CONST_SHIFT, pStreamProperties->Shift2DepthData.nConstShift); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, pStreamProperties->Shift2DepthData.nPixelSizeFactor); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, pStreamProperties->Shift2DepthData.nMaxDepthValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_SHIFT, pStreamProperties->Shift2DepthData.nMaxShiftValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PARAM_COEFF, pStreamProperties->Shift2DepthData.nParamCoeff); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHIFT_SCALE, pStreamProperties->Shift2DepthData.nShiftScale); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // set some defaults - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CONST_SHIFT, 200ULL); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, 1ULL); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, 4000ULL); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_SHIFT, 2047ULL); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PARAM_COEFF, 4ULL); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHIFT_SCALE, 10ULL); - XN_IS_STATUS_OK(nRetVal); - } - - // set compression - switch (pPackedStreamProperties->StreamDepthCompressionFormat) - { - case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); - break; - case XN_COMPRESSED_DEPTH_FORMAT_16Z: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_16Z); - break; - case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_16Z_EMB_TABLE); - break; - default: - return XN_STATUS_DEVICE_FILE_CORRUPTED; - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus BCSetImageProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_IMAGE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_IMAGE); - XN_IS_STATUS_OK(nRetVal); - - XnCropping cropping = {0}; - XnGeneralBuffer gbCropping = XN_PACK_GENERAL_BUFFER(cropping); - nRetVal = XnPropertySetAddGeneralProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_CROPPING, &gbCropping); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); - XN_IS_STATUS_OK(nRetVal); - - // set output format - XnOutputFormats nOutputFormat; - nRetVal = XnBCImageFormatToOutputFormat(pStreamProperties->ImageFormat, &nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - // set resolution - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_X_RES, (XnUInt64)pStreamProperties->nImageXRes); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_Y_RES, (XnUInt64)pStreamProperties->nImageYRes); - XN_IS_STATUS_OK(nRetVal); - - // set FPS - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_FPS, (XnUInt64)pStreamProperties->nImageFramesPerSecond); - XN_IS_STATUS_OK(nRetVal); - - // set required-output-size - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, pStreamProperties->nImageBufferSize); - XN_IS_STATUS_OK(nRetVal); - - // set bytes per pixel - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_BYTES_PER_PIXEL, pStreamProperties->nImageTypeBitSize / 8); - XN_IS_STATUS_OK(nRetVal); - - // set compression - switch (pPackedStreamProperties->StreamImageCompressionFormat) - { - case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); - break; - case XN_COMPRESSED_IMAGE_FORMAT_8Z: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_COLOR_8Z); - break; - case XN_COMPRESSED_IMAGE_FORMAT_JPEG: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_JPEG); - break; - case XN_COMPRESSED_IMAGE_FORMAT_IR10: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_10BIT_PACKED); - break; - default: - return XN_STATUS_DEVICE_FILE_CORRUPTED; - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus BCSetAudioProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_AUDIO); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_AUDIO); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); - XN_IS_STATUS_OK(nRetVal); - - // set output format - XnOutputFormats nOutputFormat; - nRetVal = XnBCAudioFormatToOutputFormat(pStreamProperties->AudioFormat, &nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - // set required-output-size - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, (XnUInt64)pStreamProperties->nAudioBufferSize); - XN_IS_STATUS_OK(nRetVal); - - // set SampleRate - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_SAMPLE_RATE, (XnUInt64)pStreamProperties->nAudioSampleRate); - XN_IS_STATUS_OK(nRetVal); - - // set number of channels - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, (XnUInt64)pStreamProperties->nAudioNumOfChannels); - XN_IS_STATUS_OK(nRetVal); - - // set chunk size - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_READ_CHUNK_SIZE, (XnUInt64)pStreamProperties->nAudioReadChunkSize); - XN_IS_STATUS_OK(nRetVal); - - // set compression - switch (pPackedStreamProperties->StreamAudioCompressionFormat) - { - case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: - nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); - break; - default: - return XN_STATUS_DEVICE_FILE_CORRUPTED; - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus ConvertStreamPropertiesToPropertySet(XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties, XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - /** DEVICE module **/ - nRetVal = XnPropertySetAddModule(pSet, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnPropertySetAddIntProperty(pSet, XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_MIRROR, (pStreamProperties->nStreamFlags & XN_STREAM_FLAG_MIRROR) == XN_STREAM_FLAG_MIRROR); - XN_IS_STATUS_OK(nRetVal); - - // we assume BC files were always recorded with low-res timestamps - nRetVal = XnPropertySetAddIntProperty(pSet, XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, FALSE); - XN_IS_STATUS_OK(nRetVal); - - /** DEPTH stream **/ - if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED && pPackedStreamProperties->StreamDepthCompressionFormat != XN_COMPRESSED_DEPTH_FORMAT_SKIP) - { - nRetVal = BCSetDepthProperties(pSet, pStreamProperties, pPackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - - /** IMAGE stream (or IR) **/ - if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED && pPackedStreamProperties->StreamImageCompressionFormat != XN_COMPRESSED_IMAGE_FORMAT_SKIP) - { - nRetVal = BCSetImageProperties(pSet, pStreamProperties, pPackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - - /** AUDIO stream **/ - if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED && pPackedStreamProperties->StreamAudioCompressionFormat != XN_COMPRESSED_AUDIO_FORMAT_SKIP) - { - nRetVal = BCSetAudioProperties(pSet, pStreamProperties, pPackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::BCCalculatePackedBufferSize() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamPropertiesV3* pStreamProperties = &m_pBCData->StreamProperties; - XnPackedStreamProperties* pPackedStreamProperties = &m_pBCData->PackedStreamProperties; - - XnUInt32 nBufferSize = 0; - - if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED) - { - if ((pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW12) || - (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW10) || - (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_SHIFTS)) - { - switch (pPackedStreamProperties->StreamDepthCompressionFormat) - { - case XN_COMPRESSED_DEPTH_FORMAT_SKIP: - break; - case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nDepthBufferSize; - break; - case XN_COMPRESSED_DEPTH_FORMAT_16Z: - case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: - nBufferSize += (XnUInt32)(pStreamProperties->nDepthBufferSize * XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT); - } - } - - if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED) - { - if ((pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_RGB24) || (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_GRAYSCALE8)) - { - switch (pPackedStreamProperties->StreamImageCompressionFormat) - { - case XN_COMPRESSED_IMAGE_FORMAT_SKIP: - break; - case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nImageBufferSize; - break; - case XN_COMPRESSED_IMAGE_FORMAT_8Z: - nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO); - break; - case XN_COMPRESSED_IMAGE_FORMAT_JPEG: - nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); - } - } - else if (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_YUV422) - { - switch (pPackedStreamProperties->StreamImageCompressionFormat) - { - case XN_COMPRESSED_IMAGE_FORMAT_SKIP: - break; - case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nImageBufferSize; - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT); - } - } - - if (pStreamProperties->MiscFormat != XN_MISC_FORMAT_DISABLED) - { - if (pStreamProperties->MiscFormat == XN_MISC_FORMAT_CONFIDENCE_MAP) - { - switch (pPackedStreamProperties->StreamMiscCompressionFormat) - { - case XN_COMPRESSED_MISC_FORMAT_SKIP: - break; - case XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nMiscBufferSize; - break; - case XN_COMPRESSED_MISC_FORMAT_CONF4: - nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); - break; - case XN_COMPRESSED_MISC_FORMAT_CONF4LZ: - nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT); - } - } - - if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED) - { - if (pStreamProperties->AudioFormat == XN_AUDIO_FORMAT_PCM) - { - switch (pPackedStreamProperties->StreamAudioCompressionFormat) - { - case XN_COMPRESSED_AUDIO_FORMAT_SKIP: - break; - case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nAudioBufferSize; - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT); - } - } - - nBufferSize += sizeof(XnPackedStreamFrameHeaderV3); - - return nBufferSize; - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::BCReadInitialState(XnPropertySet* pSet) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - XnDeviceFileHeader DeviceFileHeader; - XN_STREAM_FLAGS_TYPE nStreamFlags = 0; - - m_pBCData->nFramePos = 1; - - m_pBCData->pPackedStreamBuffer = NULL; - m_pBCData->nPackedStreamBufferSize = 0; - - // read StreamProperties - if (m_nFileVersion == 3) - { - // Current Version - nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.nMajorVersion, sizeof(XnUInt16)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.nMinorVersion, sizeof(XnUInt16)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.StreamProperties, sizeof(XnStreamPropertiesV3)); - XN_IS_STATUS_OK(nRetVal); - - DeviceFileHeader.nMajorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMajorVersion); - DeviceFileHeader.nMinorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMinorVersion); - - nRetVal = XnIOAdjustStreamPropertiesV3(&DeviceFileHeader.StreamProperties, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else if (m_nFileVersion == 2) - { - // Version 2 - DeviceFileHeader.nMajorVersion = 0; - DeviceFileHeader.nMinorVersion = 0; - XnStreamPropertiesV2 StreamPropertiesV2; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&StreamPropertiesV2, sizeof(XnStreamPropertiesV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else if (m_nFileVersion == 1) - { - // Version 1 - DeviceFileHeader.nMajorVersion = 0; - DeviceFileHeader.nMinorVersion = 0; - XnStreamPropertiesV1 StreamPropertiesV1; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&StreamPropertiesV1, sizeof(XnStreamPropertiesV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustStreamPropertiesV1(&StreamPropertiesV1, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // Bad Magic - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // read packed stream properties - switch (m_nFileVersion) - { - case 3: - { - nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV3(&DeviceFileHeader.PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 2: - { - XnPackedStreamPropertiesV2 PackedStreamPropertiesV2; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&PackedStreamPropertiesV2, sizeof(XnPackedStreamPropertiesV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV2(&PackedStreamPropertiesV2, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 1: - { - XnPackedStreamPropertiesV1 PackedStreamPropertiesV1; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&PackedStreamPropertiesV1, sizeof(XnPackedStreamPropertiesV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV1(&PackedStreamPropertiesV1, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Save the stream properties into the private data (but keep the original stream flags) - nStreamFlags = m_pBCData->StreamProperties.nStreamFlags; - xnOSMemCopy(&m_pBCData->StreamProperties, &DeviceFileHeader.StreamProperties, sizeof(XnStreamProperties)); - m_pBCData->StreamProperties.nStreamFlags = nStreamFlags; - - if (m_pBCData->StreamProperties.Shift2DepthData.bShift2DepthData) - { - m_pBCData->StreamProperties.Shift2DepthData.nMaxDepthValue = 10000; - m_pBCData->StreamProperties.nDepthMaxValue = 10000; - } - - // Save the packed stream properties into the private data - xnOSMemCopy(&m_pBCData->PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); - - XnUInt32 nBufferSize = BCCalculatePackedBufferSize(); - if (nBufferSize != m_pBCData->nPackedStreamBufferSize) - { - xnOSFree(m_pBCData->pPackedStreamBuffer); - XN_VALIDATE_ALIGNED_CALLOC(m_pBCData->pPackedStreamBuffer, XnUChar, nBufferSize, XN_DEFAULT_MEM_ALIGN); - m_pBCData->nPackedStreamBufferSize = nBufferSize; - } - - nRetVal = ConvertStreamPropertiesToPropertySet(&m_pBCData->StreamProperties, &m_pBCData->PackedStreamProperties, pSet); - XN_IS_STATUS_OK(nRetVal); - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileAdjustFileFrameHeaderV1(const XnDeviceFileFrameHeaderV1* pFileFrameHeaderV1, XnDeviceFileFrameHeaderV3* pFileFrameHeader) -{ - pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV1->nPackedStreamSize); - return XnIOAdjustStreamFramePropertiesV1(&pFileFrameHeaderV1->FrameProperties, &pFileFrameHeader->FrameProperties); -} - -XnStatus XnDeviceFileAdjustFileFrameHeaderV2(const XnDeviceFileFrameHeaderV2* pFileFrameHeaderV2, XnDeviceFileFrameHeaderV3* pFileFrameHeader) -{ - pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV2->nPackedStreamSize); - return XnIOAdjustStreamFramePropertiesV2(&pFileFrameHeaderV2->FrameProperties, &pFileFrameHeader->FrameProperties); -} - -XnStatus XnDeviceFileAdjustFileFrameHeaderV3(const XnDeviceFileFrameHeaderV3* pFileFrameHeaderV3, XnDeviceFileFrameHeaderV3* pFileFrameHeader) -{ - pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV3->nPackedStreamSize); - return XnIOAdjustStreamFramePropertiesV3(&pFileFrameHeaderV3->FrameProperties, &pFileFrameHeader->FrameProperties); -} - -XnStatus XnDeviceFileReader::BCSeek(XnUInt64 nTimestamp) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnDeviceFileReader::BCSeekFrame(XnUInt32 nFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceFileFrameHeaderV3 FileFrameHeader; - XnUInt32 nReadBytes = 0; - XnUInt32 nShouldRead = 0; - XnInt32 nExpectedFrameID = 1; - - // go back to start of file - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - - // get streams list - XnDeviceModuleHolderList streams; - nRetVal = GetStreamsList(streams); - XN_IS_STATUS_OK(nRetVal); - - // Update the frame position to the new position (treat 0 as 1) - m_pBCData->nFramePos = XN_MAX(nFrameID, 1); - - // Make sure we aren't trying to reach a frame that's beyond the number of frames - if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) - { - // Set the frame position to the last frame - m_pBCData->nFramePos = m_pBCData->StreamProperties.nNumOfFrames; - } - - // Set the file position to the first frame data (right after the file header) - XnUInt32 nOffset = 0; - switch (m_nFileVersion) - { - case 3: - nOffset = sizeof(XnDeviceFileHeader); - break; - case 2: - nOffset = sizeof(XnDeviceFileHeaderV2); - break; - case 1: - nOffset = sizeof(XnDeviceFileHeaderV1); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_HEADER); - } - - nRetVal = GetIOStream()->Seek(nOffset); - XN_IS_STATUS_OK(nRetVal); - - // If the wanted position was the first frame, we're already there - if (m_pBCData->nFramePos == 1) - { - return (XN_STATUS_OK); - } - - // Keep reading frames until we reach the wanted frame - XnUInt32 nCurrFilePos = 1; - while (nCurrFilePos < m_pBCData->nFramePos) - { - // Read the frame header - switch (m_nFileVersion) - { - case 3: - { - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV3); - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeader, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos; - } - break; - case 2: - { - XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV2); - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV2, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos - 1; - } - break; - case 1: - { - XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV1); - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV1, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos - 1; - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Make sure we got the right header size - if (nReadBytes != nShouldRead) - { - return (XN_STATUS_IO_INVALID_STREAM_FRAME_HEADER); - } - - // Skip the frame data - XnUInt32 nPosition; - nRetVal = GetIOStream()->Tell(&nPosition); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetIOStream()->Seek(FileFrameHeader.nPackedStreamSize + nPosition); - XN_IS_STATUS_OK(nRetVal); - - // increment streams frame ID - for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); - pStream->NewDataAvailable(); - } - - // Make sure frame ids are sequential - if (FileFrameHeader.FrameProperties.nDepthFrameID != nExpectedFrameID) - { - return (XN_STATUS_IO_STREAM_NOT_SEQUENTIAL); - } - - // Update the current file frame position - nCurrFilePos++; - } - - // now read last frame (the one we wanted) - XnBool bWrapOccured; - nRetVal = BCReadFrame(&bWrapOccured); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::BCReadFrame(XnBool* pbWrapOccured) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - XnDeviceFileFrameHeaderV3 FileFrameHeader; - XnUInt64 nCurrTime = 0; - XnUInt64 nDiffTime = 0; - XnUInt64 nFramesDiffTime = 0; - XnUInt32 nSleepTime = 0; - - *pbWrapOccured = FALSE; - - // If we've reached the last frame, seek back to the first one - if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) - { - nRetVal = HandleEndOfStream(); - XN_IS_STATUS_OK(nRetVal); - *pbWrapOccured = TRUE; - } - - m_bFileHasData = TRUE; - - // Note: Since this is an internal function, the pointers are assumed to be checked by the caller - // Read the frame header - switch (m_nFileVersion) - { - case 3: - { - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeader, sizeof(XnDeviceFileFrameHeaderV3)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV3(&FileFrameHeader, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 2: - { - XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV2, sizeof(XnDeviceFileFrameHeaderV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 1: - { - XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; - - nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV1, sizeof(XnDeviceFileFrameHeaderV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - FileFrameHeader.FrameProperties.nDepthFrameID = m_pBCData->nFramePos; - FileFrameHeader.FrameProperties.nImageFrameID = m_pBCData->nFramePos; - - // Make sure we aren't going to overflow the packed stream buffer - if (FileFrameHeader.nPackedStreamSize > m_pBCData->nPackedStreamBufferSize) - { - return (XN_STATUS_INPUT_BUFFER_OVERFLOW); - } - - // Read the frame packed stream data into the packed stream buffer - nRetVal = GetIOStream()->ReadData(m_pBCData->pPackedStreamBuffer, FileFrameHeader.nPackedStreamSize); - XN_IS_STATUS_OK(nRetVal); - - // read the frame header - XnPackedStreamFrameHeaderV3 PackedStreamHeader; - XnUChar* pPackedBuffer = m_pBCData->pPackedStreamBuffer; - - switch (m_nFileVersion) - { - case 0: - case 3: - { - xnOSMemCopy(&PackedStreamHeader, pPackedBuffer, sizeof(XnPackedStreamFrameHeaderV3)); - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV3); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV3(&PackedStreamHeader, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - case 2: - { - XnPackedStreamFrameHeaderV2* pPackedStreamHeaderV2 = (XnPackedStreamFrameHeaderV2*)pPackedBuffer; - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV2); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamHeaderV2, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - case 1: - { - XnPackedStreamFrameHeaderV1* pPackedStreamHeaderV1 = (XnPackedStreamFrameHeaderV1*)pPackedBuffer; - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV1); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV1(pPackedStreamHeaderV1, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Depth - XnStreamDeviceStreamHolder* pStreamHolder; - if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_DEPTH, &pStreamHolder)) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); - - XnStreamData* pStreamData = pStream->GetStreamData(); - - // check size - nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); - nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompDepthBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nDepthTimeStamp; - pStreamData->nFrameID = FileFrameHeader.FrameProperties.nDepthFrameID; - - pPackedBuffer += PackedStreamHeader.nCompDepthBufferSize; - - pStream->NewDataAvailable(); - } - - // Image - if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_IMAGE, &pStreamHolder)) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); - - XnStreamData* pStreamData = pStream->GetStreamData(); - - // check size - nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); - nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompImageBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nImageTimeStamp; - pStreamData->nFrameID = FileFrameHeader.FrameProperties.nImageFrameID; - - pPackedBuffer += PackedStreamHeader.nCompImageBufferSize; - - pStream->NewDataAvailable(); - } - - // we do not support MISC - pPackedBuffer += PackedStreamHeader.nCompMiscBufferSize; - - // Audio - if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_AUDIO, &pStreamHolder)) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); - - XnStreamData* pStreamData = pStream->GetStreamData(); - - // check size - nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); - nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompAudioBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nAudioTimeStamp; - pStreamData->nFrameID = 0; - - pPackedBuffer += PackedStreamHeader.nCompAudioBufferSize; - - pStream->NewDataAvailable(); - } - - // Increase the file frame position - m_pBCData->nFramePos++; - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileReader::BCDestroy() -{ - if (m_pBCData != NULL) - { - xnOSFreeAligned(m_pBCData->pPackedStreamBuffer); - xnOSFree(m_pBCData); - } - - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceFileReader.h" +#include "XnDeviceFileReaderBC.h" +//#include "XnFileReaderStreamHelper.h" +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnStatus XnIOAdjustStreamPropertiesV3(const XnStreamProperties* pStreamPropertiesV3, XnStreamProperties* pStreamProperties) +{ + pStreamProperties->nStreamFlags = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nStreamFlags); + pStreamProperties->nNumOfFrames = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nNumOfFrames); + pStreamProperties->nDepthFramesPerSecond = pStreamPropertiesV3->nDepthFramesPerSecond; + pStreamProperties->nImageFramesPerSecond = pStreamPropertiesV3->nImageFramesPerSecond; + pStreamProperties->DepthFormat = XnStreamDepthFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->DepthFormat))); + pStreamProperties->nDepthXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthXRes); + pStreamProperties->nDepthYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthYRes); + pStreamProperties->nDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nDepthBufferSize); + pStreamProperties->nDepthTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nDepthTypeBitSize); + pStreamProperties->nDepthMinValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthMinValue); + pStreamProperties->nDepthMaxValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthMaxValue); + pStreamProperties->nDepthNoSampleValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthNoSampleValue); + pStreamProperties->nDepthShadowValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nDepthShadowValue); + pStreamProperties->ImageFormat = XnStreamImageFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->ImageFormat))); + pStreamProperties->nImageXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nImageXRes); + pStreamProperties->nImageYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nImageYRes); + pStreamProperties->nImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nImageBufferSize); + pStreamProperties->nImageTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nImageTypeBitSize); + pStreamProperties->MiscFormat = XnStreamMiscFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->MiscFormat))); + pStreamProperties->nMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nMiscBufferSize); + pStreamProperties->nMiscTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nMiscTypeBitSize); + pStreamProperties->nZeroPlaneDistance = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV3->nZeroPlaneDistance); + pStreamProperties->fZeroPlanePixelSize = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV3->fZeroPlanePixelSize); + pStreamProperties->fEmitterDCmosDistance = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV3->fEmitterDCmosDistance); + pStreamProperties->Shift2DepthData.bShift2DepthData = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.bShift2DepthData); + pStreamProperties->Shift2DepthData.nConstShift = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nConstShift); + pStreamProperties->Shift2DepthData.nPixelSizeFactor = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nPixelSizeFactor); + pStreamProperties->Shift2DepthData.nMaxShiftValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nMaxShiftValue); + pStreamProperties->Shift2DepthData.nMaxDepthValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nMaxDepthValue); + pStreamProperties->Shift2DepthData.nParamCoeff = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nParamCoeff); + pStreamProperties->Shift2DepthData.nShiftScale = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->Shift2DepthData.nShiftScale); + pStreamProperties->AudioFormat = XnStreamAudioFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->AudioFormat))); + pStreamProperties->nAudioNumOfChannels = pStreamPropertiesV3->nAudioNumOfChannels; + pStreamProperties->nAudioSampleRate = XnSampleRate(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV3->nAudioSampleRate))); + pStreamProperties->nAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nAudioBufferSize); + pStreamProperties->AudioReadMode = pStreamPropertiesV3->AudioReadMode; + pStreamProperties->nAudioReadChunkSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV3->nAudioReadChunkSize); + + return (XN_STATUS_OK); +} + +XnStatus XnIOAdjustStreamPropertiesV2 (const XnStreamPropertiesV2* pStreamPropertiesV2, XnStreamProperties* pStreamProperties) +{ + pStreamProperties->nStreamFlags = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nStreamFlags); + pStreamProperties->nNumOfFrames = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nNumOfFrames); + pStreamProperties->nDepthFramesPerSecond = pStreamPropertiesV2->nDepthFramesPerSecond; + pStreamProperties->nImageFramesPerSecond = pStreamPropertiesV2->nImageFramesPerSecond; + pStreamProperties->DepthFormat = XnStreamDepthFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->DepthFormat))); + pStreamProperties->nDepthXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthXRes); + pStreamProperties->nDepthYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthYRes); + pStreamProperties->nDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nDepthBufferSize); + pStreamProperties->nDepthTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nDepthTypeBitSize); + pStreamProperties->nDepthMinValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthMinValue); + pStreamProperties->nDepthMaxValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthMaxValue); + pStreamProperties->nDepthNoSampleValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthNoSampleValue); + pStreamProperties->nDepthShadowValue = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nDepthShadowValue); + pStreamProperties->ImageFormat = XnStreamImageFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->ImageFormat))); + pStreamProperties->nImageXRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nImageXRes); + pStreamProperties->nImageYRes = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nImageYRes); + pStreamProperties->nImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nImageBufferSize); + pStreamProperties->nImageTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nImageTypeBitSize); + pStreamProperties->MiscFormat = XnStreamMiscFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(pStreamPropertiesV2->MiscFormat))); + pStreamProperties->nMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nMiscBufferSize); + pStreamProperties->nMiscTypeBitSize = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->nMiscTypeBitSize); + pStreamProperties->nZeroPlaneDistance = XN_PREPARE_VAR16_IN_BUFFER(pStreamPropertiesV2->nZeroPlaneDistance); + pStreamProperties->fZeroPlanePixelSize = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV2->fZeroPlanePixelSize); + pStreamProperties->fEmitterDCmosDistance = XN_PREPARE_VAR_FLOAT_IN_BUFFER(pStreamPropertiesV2->fEmitterDCmosDistance); + pStreamProperties->Shift2DepthData.bShift2DepthData = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.bShift2DepthData); + pStreamProperties->Shift2DepthData.nConstShift = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nConstShift); + pStreamProperties->Shift2DepthData.nPixelSizeFactor = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nPixelSizeFactor); + pStreamProperties->Shift2DepthData.nMaxShiftValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nMaxShiftValue); + pStreamProperties->Shift2DepthData.nMaxDepthValue = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nMaxDepthValue); + pStreamProperties->Shift2DepthData.nParamCoeff = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nParamCoeff); + pStreamProperties->Shift2DepthData.nShiftScale = XN_PREPARE_VAR32_IN_BUFFER(pStreamPropertiesV2->Shift2DepthData.nShiftScale); + + // fix old bug: in versions 2.x (until 2.6) pixel size was written 2 when decimation was enabled + // where it should be 2 when decimation is disabled. We don't know if decimation was used or not, + // so we deduce it from the FPS and resolution. + // In this case, we need to fix the pixel size factor. + if (pStreamProperties->Shift2DepthData.nPixelSizeFactor == 2 && pStreamProperties->nDepthXRes == 320 && pStreamProperties->nDepthFramesPerSecond == 30) + pStreamProperties->Shift2DepthData.nPixelSizeFactor = 1; + + pStreamProperties->AudioFormat = XnStreamAudioFormat(XN_PREPARE_VAR32_IN_BUFFER(XnUInt32(XN_AUDIO_FORMAT_DISABLED))); + pStreamProperties->nAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(0); + + return (XN_STATUS_OK); +} + +XnStatus XnIOAdjustStreamPropertiesV1 (const XnStreamPropertiesV1* pStreamPropertiesV1, XnStreamProperties* pStreamProperties) +{ + // adjust from V1 to V2 + XnStreamPropertiesV2 StreamPropertiesV2; + + StreamPropertiesV2.nStreamFlags = pStreamPropertiesV1->nStreamFlags; + StreamPropertiesV2.nNumOfFrames = pStreamPropertiesV1->nNumOfFrames; + StreamPropertiesV2.nDepthFramesPerSecond = pStreamPropertiesV1->nFramesPerSecond; + StreamPropertiesV2.nImageFramesPerSecond = pStreamPropertiesV1->nFramesPerSecond; + StreamPropertiesV2.DepthFormat = pStreamPropertiesV1->DepthFormat; + StreamPropertiesV2.nDepthXRes = pStreamPropertiesV1->nDepthXRes; + StreamPropertiesV2.nDepthYRes = pStreamPropertiesV1->nDepthYRes; + StreamPropertiesV2.nDepthBufferSize = pStreamPropertiesV1->nDepthBufferSize; + StreamPropertiesV2.nDepthTypeBitSize = pStreamPropertiesV1->nDepthTypeBitSize; + StreamPropertiesV2.nDepthMinValue = pStreamPropertiesV1->nDepthMinValue; + StreamPropertiesV2.nDepthMaxValue = pStreamPropertiesV1->nDepthMaxValue; + StreamPropertiesV2.nDepthNoSampleValue = pStreamPropertiesV1->nDepthNoSampleValue; + StreamPropertiesV2.nDepthShadowValue = pStreamPropertiesV1->nDepthShadowValue; + StreamPropertiesV2.ImageFormat = pStreamPropertiesV1->ImageFormat; + StreamPropertiesV2.nImageXRes = pStreamPropertiesV1->nImageXRes; + StreamPropertiesV2.nImageYRes = pStreamPropertiesV1->nImageYRes; + StreamPropertiesV2.nImageBufferSize = pStreamPropertiesV1->nImageBufferSize; + StreamPropertiesV2.nImageTypeBitSize = pStreamPropertiesV1->nImageTypeBitSize; + StreamPropertiesV2.MiscFormat = pStreamPropertiesV1->MiscFormat; + StreamPropertiesV2.nMiscBufferSize = pStreamPropertiesV1->nMiscBufferSize; + StreamPropertiesV2.nMiscTypeBitSize = pStreamPropertiesV1->nMiscTypeBitSize; + StreamPropertiesV2.nZeroPlaneDistance = pStreamPropertiesV1->nZeroPlaneDistance; + StreamPropertiesV2.fZeroPlanePixelSize = pStreamPropertiesV1->fZeroPlanePixelSize; + StreamPropertiesV2.fEmitterDCmosDistance = 11; + StreamPropertiesV2.Shift2DepthData.bShift2DepthData = false; + + // 1.4 Code: 1280/XRes. this is the factor, to be multiplied with 2. + StreamPropertiesV2.Shift2DepthData.nPixelSizeFactor = (1280/2)/StreamPropertiesV2.nDepthXRes; + + // and now adjust from V2 to current + return XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, pStreamProperties); +} + +XnStatus XnIOAdjustStreamFramePropertiesV3(const XnStreamFrameProperties* pStreamFramePropertiesV3, XnStreamFrameProperties* pStreamFrameProperties) +{ + pStreamFrameProperties->nDepthFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV3->nDepthFrameID); + pStreamFrameProperties->nImageFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV3->nImageFrameID); + pStreamFrameProperties->nDepthTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nDepthTimeStamp); + pStreamFrameProperties->nImageTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nImageTimeStamp); + pStreamFrameProperties->nAudioTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV3->nAudioTimeStamp); + + return (XN_STATUS_OK); +} + +XnStatus XnIOAdjustStreamFramePropertiesV2 (const XnStreamFramePropertiesV2* pStreamFramePropertiesV2, XnStreamFrameProperties* pStreamFrameProperties) +{ + pStreamFrameProperties->nDepthFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV2->nDepthFrameID); + pStreamFrameProperties->nImageFrameID = XN_PREPARE_VAR32_IN_BUFFER(pStreamFramePropertiesV2->nImageFrameID); + pStreamFrameProperties->nDepthTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV2->nDepthTimeStamp); + pStreamFrameProperties->nImageTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(pStreamFramePropertiesV2->nImageTimeStamp); + pStreamFrameProperties->nAudioTimeStamp = XN_PREPARE_VAR64_IN_BUFFER(0); + + return (XN_STATUS_OK); +} + +XnStatus XnIOAdjustStreamFramePropertiesV1 (const XnStreamFramePropertiesV1* pStreamFramePropertiesV1, XnStreamFrameProperties* pStreamFrameProperties) +{ + // adjust to V2 + XnStreamFramePropertiesV2 StreamFramePropertiesV2; + + StreamFramePropertiesV2.nDepthFrameID = pStreamFramePropertiesV1->nFrameID; + StreamFramePropertiesV2.nImageFrameID = pStreamFramePropertiesV1->nFrameID; + StreamFramePropertiesV2.nDepthTimeStamp = pStreamFramePropertiesV1->nTimeStamp; + StreamFramePropertiesV2.nImageTimeStamp = pStreamFramePropertiesV1->nTimeStamp; + + // and now adjust from V2 to current + return XnIOAdjustStreamFramePropertiesV2(&StreamFramePropertiesV2, pStreamFrameProperties); +} + +XnStatus XnIOAdjustPackedStreamPropertiesV2 (const XnPackedStreamPropertiesV2* pPackedStreamPropertiesV2, XnPackedStreamProperties* pPackedStreamProperties) +{ + pPackedStreamProperties->StreamDepthCompressionFormat = XnStreamDepthCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamDepthCompressionFormat)); + pPackedStreamProperties->StreamImageCompressionFormat = XnStreamImageCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamImageCompressionFormat)); + pPackedStreamProperties->StreamMiscCompressionFormat = XnStreamMiscCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV2->StreamMiscCompressionFormat)); + pPackedStreamProperties->StreamAudioCompressionFormat = XnStreamAudioCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(XN_COMPRESSED_AUDIO_FORMAT_SKIP)); + + return XN_STATUS_OK; +} + +XnStatus XnIOAdjustPackedStreamFrameHeaderV2 (const XnPackedStreamFrameHeaderV2* pPackedStreamFrameHeaderV2, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) +{ + pPackedStreamFrameHeader->nCompDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompDepthBufferSize); + pPackedStreamFrameHeader->nCompImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompImageBufferSize); + pPackedStreamFrameHeader->nCompMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV2->nCompMiscBufferSize); + pPackedStreamFrameHeader->nCompAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(0); + + return XN_STATUS_OK; +} + +XnStatus XnIOAdjustPackedStreamPropertiesV1 (const XnPackedStreamPropertiesV1* pPackedStreamPropertiesV1, XnPackedStreamProperties* pPackedStreamProperties) +{ + // V1 and V2 are the same, so adjust from V2 to current + return XnIOAdjustPackedStreamPropertiesV2(pPackedStreamPropertiesV1, pPackedStreamProperties); +} + +XnStatus XnIOAdjustPackedStreamFrameHeaderV1 (const XnPackedStreamFrameHeaderV1* pPackedStreamFrameHeaderV1, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) +{ + // V1 and V2 are the same, so adjust from V2 to current + return XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamFrameHeaderV1, pPackedStreamFrameHeader); +} + +XnStatus XnIOAdjustPackedStreamPropertiesV3 (const XnPackedStreamProperties* pPackedStreamPropertiesV3, XnPackedStreamProperties* pPackedStreamProperties) +{ + pPackedStreamProperties->StreamDepthCompressionFormat = XnStreamDepthCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamDepthCompressionFormat)); + pPackedStreamProperties->StreamImageCompressionFormat = XnStreamImageCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamImageCompressionFormat)); + pPackedStreamProperties->StreamMiscCompressionFormat = XnStreamMiscCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamMiscCompressionFormat)); + pPackedStreamProperties->StreamAudioCompressionFormat = XnStreamAudioCompressionFormat(XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamPropertiesV3->StreamAudioCompressionFormat)); + + return XN_STATUS_OK; +} + +XnStatus XnIOAdjustPackedStreamFrameHeaderV3 (const XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeaderV3, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader) +{ + pPackedStreamFrameHeader->nCompDepthBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompDepthBufferSize); + pPackedStreamFrameHeader->nCompImageBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompImageBufferSize); + pPackedStreamFrameHeader->nCompMiscBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompMiscBufferSize); + pPackedStreamFrameHeader->nCompAudioBufferSize = XN_PREPARE_VAR32_IN_BUFFER(pPackedStreamFrameHeaderV3->nCompAudioBufferSize); + + return XN_STATUS_OK; +} + +XnStatus XnDeviceFileReader::BCInit() +{ + XN_VALIDATE_CALLOC(m_pBCData, XnFileBCData, 1); + return XN_STATUS_OK; +} + +XnStatus BCSetDepthProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_DEPTH); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_DEPTH); + XN_IS_STATUS_OK(nRetVal); + + XnCropping cropping = {0}; + XnGeneralBuffer gbCropping = XN_PACK_GENERAL_BUFFER(cropping); + nRetVal = XnPropertySetAddGeneralProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CROPPING, &gbCropping); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); + XN_IS_STATUS_OK(nRetVal); + + // set output format + XnOutputFormats nOutputFormat; + nRetVal = XnBCDepthFormatToOutputFormat(pStreamProperties->DepthFormat, &nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + // set resolution + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_X_RES, (XnUInt64)pStreamProperties->nDepthXRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_Y_RES, (XnUInt64)pStreamProperties->nDepthYRes); + XN_IS_STATUS_OK(nRetVal); + + // set FPS + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_FPS, (XnUInt64)pStreamProperties->nDepthFramesPerSecond); + XN_IS_STATUS_OK(nRetVal); + + // set required-output-size + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, pStreamProperties->nDepthBufferSize); + XN_IS_STATUS_OK(nRetVal); + + // set bytes per pixel + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_BYTES_PER_PIXEL, pStreamProperties->nDepthTypeBitSize / 8); + XN_IS_STATUS_OK(nRetVal); + + // set cut-off + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_DEPTH, (XnUInt64)pStreamProperties->nDepthMaxValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MIN_DEPTH, (XnUInt64)pStreamProperties->nDepthMinValue); + XN_IS_STATUS_OK(nRetVal); + + // no-value and shadow-value + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_NO_SAMPLE, pStreamProperties->nDepthNoSampleValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHADOW, pStreamProperties->nDepthShadowValue); + XN_IS_STATUS_OK(nRetVal); + + // zero plane + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, pStreamProperties->nZeroPlaneDistance); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddRealProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, pStreamProperties->fZeroPlanePixelSize); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddRealProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, pStreamProperties->fEmitterDCmosDistance); + XN_IS_STATUS_OK(nRetVal); + + // shift-to-depth + if (pStreamProperties->Shift2DepthData.bShift2DepthData) + { + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CONST_SHIFT, pStreamProperties->Shift2DepthData.nConstShift); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, pStreamProperties->Shift2DepthData.nPixelSizeFactor); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, pStreamProperties->Shift2DepthData.nMaxDepthValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_SHIFT, pStreamProperties->Shift2DepthData.nMaxShiftValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PARAM_COEFF, pStreamProperties->Shift2DepthData.nParamCoeff); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHIFT_SCALE, pStreamProperties->Shift2DepthData.nShiftScale); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // set some defaults + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_CONST_SHIFT, 200ULL); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, 1ULL); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, 4000ULL); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_MAX_SHIFT, 2047ULL); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_PARAM_COEFF, 4ULL); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_SHIFT_SCALE, 10ULL); + XN_IS_STATUS_OK(nRetVal); + } + + // set compression + switch (pPackedStreamProperties->StreamDepthCompressionFormat) + { + case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); + break; + case XN_COMPRESSED_DEPTH_FORMAT_16Z: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_16Z); + break; + case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_DEPTH, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_16Z_EMB_TABLE); + break; + default: + return XN_STATUS_DEVICE_FILE_CORRUPTED; + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus BCSetImageProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_IMAGE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_IMAGE); + XN_IS_STATUS_OK(nRetVal); + + XnCropping cropping = {0}; + XnGeneralBuffer gbCropping = XN_PACK_GENERAL_BUFFER(cropping); + nRetVal = XnPropertySetAddGeneralProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_CROPPING, &gbCropping); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); + XN_IS_STATUS_OK(nRetVal); + + // set output format + XnOutputFormats nOutputFormat; + nRetVal = XnBCImageFormatToOutputFormat(pStreamProperties->ImageFormat, &nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + // set resolution + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_X_RES, (XnUInt64)pStreamProperties->nImageXRes); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_Y_RES, (XnUInt64)pStreamProperties->nImageYRes); + XN_IS_STATUS_OK(nRetVal); + + // set FPS + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_FPS, (XnUInt64)pStreamProperties->nImageFramesPerSecond); + XN_IS_STATUS_OK(nRetVal); + + // set required-output-size + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, pStreamProperties->nImageBufferSize); + XN_IS_STATUS_OK(nRetVal); + + // set bytes per pixel + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_BYTES_PER_PIXEL, pStreamProperties->nImageTypeBitSize / 8); + XN_IS_STATUS_OK(nRetVal); + + // set compression + switch (pPackedStreamProperties->StreamImageCompressionFormat) + { + case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); + break; + case XN_COMPRESSED_IMAGE_FORMAT_8Z: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_COLOR_8Z); + break; + case XN_COMPRESSED_IMAGE_FORMAT_JPEG: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_JPEG); + break; + case XN_COMPRESSED_IMAGE_FORMAT_IR10: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_IMAGE, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_10BIT_PACKED); + break; + default: + return XN_STATUS_DEVICE_FILE_CORRUPTED; + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus BCSetAudioProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnPropertySetAddModule(pSet, XN_STREAM_NAME_AUDIO); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddStringProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_TYPE, XN_STREAM_TYPE_AUDIO); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, (XnUInt64)pStreamProperties->nNumOfFrames); + XN_IS_STATUS_OK(nRetVal); + + // set output format + XnOutputFormats nOutputFormat; + nRetVal = XnBCAudioFormatToOutputFormat(pStreamProperties->AudioFormat, &nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + // set required-output-size + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, (XnUInt64)pStreamProperties->nAudioBufferSize); + XN_IS_STATUS_OK(nRetVal); + + // set SampleRate + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_SAMPLE_RATE, (XnUInt64)pStreamProperties->nAudioSampleRate); + XN_IS_STATUS_OK(nRetVal); + + // set number of channels + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, (XnUInt64)pStreamProperties->nAudioNumOfChannels); + XN_IS_STATUS_OK(nRetVal); + + // set chunk size + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_READ_CHUNK_SIZE, (XnUInt64)pStreamProperties->nAudioReadChunkSize); + XN_IS_STATUS_OK(nRetVal); + + // set compression + switch (pPackedStreamProperties->StreamAudioCompressionFormat) + { + case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: + nRetVal = XnPropertySetAddIntProperty(pSet, XN_STREAM_NAME_AUDIO, XN_STREAM_PROPERTY_COMPRESSION, (XnUInt64)XN_COMPRESSION_NONE); + break; + default: + return XN_STATUS_DEVICE_FILE_CORRUPTED; + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus ConvertStreamPropertiesToPropertySet(XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties, XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + /** DEVICE module **/ + nRetVal = XnPropertySetAddModule(pSet, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(pSet, XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_MIRROR, (pStreamProperties->nStreamFlags & XN_STREAM_FLAG_MIRROR) == XN_STREAM_FLAG_MIRROR); + XN_IS_STATUS_OK(nRetVal); + + // we assume BC files were always recorded with low-res timestamps + nRetVal = XnPropertySetAddIntProperty(pSet, XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, FALSE); + XN_IS_STATUS_OK(nRetVal); + + /** DEPTH stream **/ + if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED && pPackedStreamProperties->StreamDepthCompressionFormat != XN_COMPRESSED_DEPTH_FORMAT_SKIP) + { + nRetVal = BCSetDepthProperties(pSet, pStreamProperties, pPackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + + /** IMAGE stream (or IR) **/ + if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED && pPackedStreamProperties->StreamImageCompressionFormat != XN_COMPRESSED_IMAGE_FORMAT_SKIP) + { + nRetVal = BCSetImageProperties(pSet, pStreamProperties, pPackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + + /** AUDIO stream **/ + if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED && pPackedStreamProperties->StreamAudioCompressionFormat != XN_COMPRESSED_AUDIO_FORMAT_SKIP) + { + nRetVal = BCSetAudioProperties(pSet, pStreamProperties, pPackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::BCCalculatePackedBufferSize() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamPropertiesV3* pStreamProperties = &m_pBCData->StreamProperties; + XnPackedStreamProperties* pPackedStreamProperties = &m_pBCData->PackedStreamProperties; + + XnUInt32 nBufferSize = 0; + + if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED) + { + if ((pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW12) || + (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW10) || + (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_SHIFTS)) + { + switch (pPackedStreamProperties->StreamDepthCompressionFormat) + { + case XN_COMPRESSED_DEPTH_FORMAT_SKIP: + break; + case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nDepthBufferSize; + break; + case XN_COMPRESSED_DEPTH_FORMAT_16Z: + case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: + nBufferSize += (XnUInt32)(pStreamProperties->nDepthBufferSize * XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT); + } + } + + if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED) + { + if ((pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_RGB24) || (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_GRAYSCALE8)) + { + switch (pPackedStreamProperties->StreamImageCompressionFormat) + { + case XN_COMPRESSED_IMAGE_FORMAT_SKIP: + break; + case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nImageBufferSize; + break; + case XN_COMPRESSED_IMAGE_FORMAT_8Z: + nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO); + break; + case XN_COMPRESSED_IMAGE_FORMAT_JPEG: + nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); + } + } + else if (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_YUV422) + { + switch (pPackedStreamProperties->StreamImageCompressionFormat) + { + case XN_COMPRESSED_IMAGE_FORMAT_SKIP: + break; + case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nImageBufferSize; + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT); + } + } + + if (pStreamProperties->MiscFormat != XN_MISC_FORMAT_DISABLED) + { + if (pStreamProperties->MiscFormat == XN_MISC_FORMAT_CONFIDENCE_MAP) + { + switch (pPackedStreamProperties->StreamMiscCompressionFormat) + { + case XN_COMPRESSED_MISC_FORMAT_SKIP: + break; + case XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nMiscBufferSize; + break; + case XN_COMPRESSED_MISC_FORMAT_CONF4: + nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); + break; + case XN_COMPRESSED_MISC_FORMAT_CONF4LZ: + nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT); + } + } + + if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED) + { + if (pStreamProperties->AudioFormat == XN_AUDIO_FORMAT_PCM) + { + switch (pPackedStreamProperties->StreamAudioCompressionFormat) + { + case XN_COMPRESSED_AUDIO_FORMAT_SKIP: + break; + case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nAudioBufferSize; + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT); + } + } + + nBufferSize += sizeof(XnPackedStreamFrameHeaderV3); + + return nBufferSize; + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::BCReadInitialState(XnPropertySet* pSet) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + XnDeviceFileHeader DeviceFileHeader; + XN_STREAM_FLAGS_TYPE nStreamFlags = 0; + + m_pBCData->nFramePos = 1; + + m_pBCData->pPackedStreamBuffer = NULL; + m_pBCData->nPackedStreamBufferSize = 0; + + // read StreamProperties + if (m_nFileVersion == 3) + { + // Current Version + nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.nMajorVersion, sizeof(XnUInt16)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.nMinorVersion, sizeof(XnUInt16)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.StreamProperties, sizeof(XnStreamPropertiesV3)); + XN_IS_STATUS_OK(nRetVal); + + DeviceFileHeader.nMajorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMajorVersion); + DeviceFileHeader.nMinorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMinorVersion); + + nRetVal = XnIOAdjustStreamPropertiesV3(&DeviceFileHeader.StreamProperties, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else if (m_nFileVersion == 2) + { + // Version 2 + DeviceFileHeader.nMajorVersion = 0; + DeviceFileHeader.nMinorVersion = 0; + XnStreamPropertiesV2 StreamPropertiesV2; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&StreamPropertiesV2, sizeof(XnStreamPropertiesV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else if (m_nFileVersion == 1) + { + // Version 1 + DeviceFileHeader.nMajorVersion = 0; + DeviceFileHeader.nMinorVersion = 0; + XnStreamPropertiesV1 StreamPropertiesV1; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&StreamPropertiesV1, sizeof(XnStreamPropertiesV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustStreamPropertiesV1(&StreamPropertiesV1, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // Bad Magic + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // read packed stream properties + switch (m_nFileVersion) + { + case 3: + { + nRetVal = GetIOStream()->ReadData((XnUChar*)&DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV3(&DeviceFileHeader.PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 2: + { + XnPackedStreamPropertiesV2 PackedStreamPropertiesV2; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&PackedStreamPropertiesV2, sizeof(XnPackedStreamPropertiesV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV2(&PackedStreamPropertiesV2, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 1: + { + XnPackedStreamPropertiesV1 PackedStreamPropertiesV1; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&PackedStreamPropertiesV1, sizeof(XnPackedStreamPropertiesV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV1(&PackedStreamPropertiesV1, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Save the stream properties into the private data (but keep the original stream flags) + nStreamFlags = m_pBCData->StreamProperties.nStreamFlags; + xnOSMemCopy(&m_pBCData->StreamProperties, &DeviceFileHeader.StreamProperties, sizeof(XnStreamProperties)); + m_pBCData->StreamProperties.nStreamFlags = nStreamFlags; + + if (m_pBCData->StreamProperties.Shift2DepthData.bShift2DepthData) + { + m_pBCData->StreamProperties.Shift2DepthData.nMaxDepthValue = 10000; + m_pBCData->StreamProperties.nDepthMaxValue = 10000; + } + + // Save the packed stream properties into the private data + xnOSMemCopy(&m_pBCData->PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); + + XnUInt32 nBufferSize = BCCalculatePackedBufferSize(); + if (nBufferSize != m_pBCData->nPackedStreamBufferSize) + { + xnOSFree(m_pBCData->pPackedStreamBuffer); + XN_VALIDATE_ALIGNED_CALLOC(m_pBCData->pPackedStreamBuffer, XnUChar, nBufferSize, XN_DEFAULT_MEM_ALIGN); + m_pBCData->nPackedStreamBufferSize = nBufferSize; + } + + nRetVal = ConvertStreamPropertiesToPropertySet(&m_pBCData->StreamProperties, &m_pBCData->PackedStreamProperties, pSet); + XN_IS_STATUS_OK(nRetVal); + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileAdjustFileFrameHeaderV1(const XnDeviceFileFrameHeaderV1* pFileFrameHeaderV1, XnDeviceFileFrameHeaderV3* pFileFrameHeader) +{ + pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV1->nPackedStreamSize); + return XnIOAdjustStreamFramePropertiesV1(&pFileFrameHeaderV1->FrameProperties, &pFileFrameHeader->FrameProperties); +} + +XnStatus XnDeviceFileAdjustFileFrameHeaderV2(const XnDeviceFileFrameHeaderV2* pFileFrameHeaderV2, XnDeviceFileFrameHeaderV3* pFileFrameHeader) +{ + pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV2->nPackedStreamSize); + return XnIOAdjustStreamFramePropertiesV2(&pFileFrameHeaderV2->FrameProperties, &pFileFrameHeader->FrameProperties); +} + +XnStatus XnDeviceFileAdjustFileFrameHeaderV3(const XnDeviceFileFrameHeaderV3* pFileFrameHeaderV3, XnDeviceFileFrameHeaderV3* pFileFrameHeader) +{ + pFileFrameHeader->nPackedStreamSize = XN_PREPARE_VAR32_IN_BUFFER(pFileFrameHeaderV3->nPackedStreamSize); + return XnIOAdjustStreamFramePropertiesV3(&pFileFrameHeaderV3->FrameProperties, &pFileFrameHeader->FrameProperties); +} + +XnStatus XnDeviceFileReader::BCSeek(XnUInt64 nTimestamp) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnDeviceFileReader::BCSeekFrame(XnUInt32 nFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceFileFrameHeaderV3 FileFrameHeader; + XnUInt32 nReadBytes = 0; + XnUInt32 nShouldRead = 0; + XnInt32 nExpectedFrameID = 1; + + // go back to start of file + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + + // get streams list + XnDeviceModuleHolderList streams; + nRetVal = GetStreamsList(streams); + XN_IS_STATUS_OK(nRetVal); + + // Update the frame position to the new position (treat 0 as 1) + m_pBCData->nFramePos = XN_MAX(nFrameID, 1); + + // Make sure we aren't trying to reach a frame that's beyond the number of frames + if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) + { + // Set the frame position to the last frame + m_pBCData->nFramePos = m_pBCData->StreamProperties.nNumOfFrames; + } + + // Set the file position to the first frame data (right after the file header) + XnUInt32 nOffset = 0; + switch (m_nFileVersion) + { + case 3: + nOffset = sizeof(XnDeviceFileHeader); + break; + case 2: + nOffset = sizeof(XnDeviceFileHeaderV2); + break; + case 1: + nOffset = sizeof(XnDeviceFileHeaderV1); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_HEADER); + } + + nRetVal = GetIOStream()->Seek(nOffset); + XN_IS_STATUS_OK(nRetVal); + + // If the wanted position was the first frame, we're already there + if (m_pBCData->nFramePos == 1) + { + return (XN_STATUS_OK); + } + + // Keep reading frames until we reach the wanted frame + XnUInt32 nCurrFilePos = 1; + while (nCurrFilePos < m_pBCData->nFramePos) + { + // Read the frame header + switch (m_nFileVersion) + { + case 3: + { + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV3); + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeader, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos; + } + break; + case 2: + { + XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV2); + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV2, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos - 1; + } + break; + case 1: + { + XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV1); + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV1, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos - 1; + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Make sure we got the right header size + if (nReadBytes != nShouldRead) + { + return (XN_STATUS_IO_INVALID_STREAM_FRAME_HEADER); + } + + // Skip the frame data + XnUInt32 nPosition; + nRetVal = GetIOStream()->Tell(&nPosition); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetIOStream()->Seek(FileFrameHeader.nPackedStreamSize + nPosition); + XN_IS_STATUS_OK(nRetVal); + + // increment streams frame ID + for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); + pStream->NewDataAvailable(0, 0); + } + + // Make sure frame ids are sequential + if (FileFrameHeader.FrameProperties.nDepthFrameID != nExpectedFrameID) + { + return (XN_STATUS_IO_STREAM_NOT_SEQUENTIAL); + } + + // Update the current file frame position + nCurrFilePos++; + } + + // now read last frame (the one we wanted) + XnBool bWrapOccured; + nRetVal = BCReadFrame(&bWrapOccured); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::BCReadFrame(XnBool* pbWrapOccured) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + XnDeviceFileFrameHeaderV3 FileFrameHeader; + XnUInt64 nCurrTime = 0; + XnUInt64 nDiffTime = 0; + XnUInt64 nFramesDiffTime = 0; + XnUInt32 nSleepTime = 0; + + *pbWrapOccured = FALSE; + + // If we've reached the last frame, seek back to the first one + if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) + { + nRetVal = HandleEndOfStream(); + XN_IS_STATUS_OK(nRetVal); + *pbWrapOccured = TRUE; + } + + m_bFileHasData = TRUE; + + // Note: Since this is an internal function, the pointers are assumed to be checked by the caller + // Read the frame header + switch (m_nFileVersion) + { + case 3: + { + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeader, sizeof(XnDeviceFileFrameHeaderV3)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV3(&FileFrameHeader, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 2: + { + XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV2, sizeof(XnDeviceFileFrameHeaderV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 1: + { + XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; + + nRetVal = GetIOStream()->ReadData((XnUChar*)&FileFrameHeaderV1, sizeof(XnDeviceFileFrameHeaderV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + FileFrameHeader.FrameProperties.nDepthFrameID = m_pBCData->nFramePos; + FileFrameHeader.FrameProperties.nImageFrameID = m_pBCData->nFramePos; + + // Make sure we aren't going to overflow the packed stream buffer + if (FileFrameHeader.nPackedStreamSize > m_pBCData->nPackedStreamBufferSize) + { + return (XN_STATUS_INPUT_BUFFER_OVERFLOW); + } + + // Read the frame packed stream data into the packed stream buffer + nRetVal = GetIOStream()->ReadData(m_pBCData->pPackedStreamBuffer, FileFrameHeader.nPackedStreamSize); + XN_IS_STATUS_OK(nRetVal); + + // read the frame header + XnPackedStreamFrameHeaderV3 PackedStreamHeader; + XnUChar* pPackedBuffer = m_pBCData->pPackedStreamBuffer; + + switch (m_nFileVersion) + { + case 0: + case 3: + { + xnOSMemCopy(&PackedStreamHeader, pPackedBuffer, sizeof(XnPackedStreamFrameHeaderV3)); + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV3); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV3(&PackedStreamHeader, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + case 2: + { + XnPackedStreamFrameHeaderV2* pPackedStreamHeaderV2 = (XnPackedStreamFrameHeaderV2*)pPackedBuffer; + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV2); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamHeaderV2, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + case 1: + { + XnPackedStreamFrameHeaderV1* pPackedStreamHeaderV1 = (XnPackedStreamFrameHeaderV1*)pPackedBuffer; + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV1); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV1(pPackedStreamHeaderV1, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Depth + XnStreamDeviceStreamHolder* pStreamHolder; + if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_DEPTH, &pStreamHolder)) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); + + XnStreamData* pStreamData = pStream->GetStreamData(); + + // check size + nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); + nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompDepthBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nDepthTimeStamp; + pStreamData->nFrameID = FileFrameHeader.FrameProperties.nDepthFrameID; + + pPackedBuffer += PackedStreamHeader.nCompDepthBufferSize; + + pStream->NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); + } + + // Image + if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_IMAGE, &pStreamHolder)) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); + + XnStreamData* pStreamData = pStream->GetStreamData(); + + // check size + nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); + nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompImageBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nImageTimeStamp; + pStreamData->nFrameID = FileFrameHeader.FrameProperties.nImageFrameID; + + pPackedBuffer += PackedStreamHeader.nCompImageBufferSize; + + pStream->NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); + } + + // we do not support MISC + pPackedBuffer += PackedStreamHeader.nCompMiscBufferSize; + + // Audio + if (XN_STATUS_OK == FindStream(XN_STREAM_NAME_AUDIO, &pStreamHolder)) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)pStreamHolder->GetStream(); + + XnStreamData* pStreamData = pStream->GetStreamData(); + + // check size + nRetVal = XnStreamDataCheckSize(pStreamData, pStream->GetRequiredDataSize()); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nDataSize = pStreamHolder->GetStream()->GetRequiredDataSize(); + nRetVal = pStreamHolder->GetCodec()->Decompress(pPackedBuffer, PackedStreamHeader.nCompAudioBufferSize, (XnUChar*)pStreamData->pData, &pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->nTimestamp = FileFrameHeader.FrameProperties.nAudioTimeStamp; + pStreamData->nFrameID = 0; + + pPackedBuffer += PackedStreamHeader.nCompAudioBufferSize; + + pStream->NewDataAvailable(pStreamData->nTimestamp, pStreamData->nFrameID); + } + + // Increase the file frame position + m_pBCData->nFramePos++; + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileReader::BCDestroy() +{ + if (m_pBCData != NULL) + { + xnOSFreeAligned(m_pBCData->pPackedStreamBuffer); + xnOSFree(m_pBCData); + } + + return XN_STATUS_OK; +} diff --git a/Source/XnDeviceFile/XnDeviceFileReaderBC.h b/Source/XnDeviceFile/XnDeviceFileReaderBC.h index 6cb0ed1..5240113 100644 --- a/Source/XnDeviceFile/XnDeviceFileReaderBC.h +++ b/Source/XnDeviceFile/XnDeviceFileReaderBC.h @@ -1,403 +1,403 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_DEVICE_FILE_READER_BC_H_ -#define _XN_DEVICE_FILE_READER_BC_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceFile.h" - -#define _XN_IO_BC -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -#pragma pack (push, 1) - -typedef struct XnPackedStreamProperties -{ - XnStreamDepthCompressionFormat StreamDepthCompressionFormat; - XnStreamImageCompressionFormat StreamImageCompressionFormat; - XnStreamMiscCompressionFormat StreamMiscCompressionFormat; - XnStreamAudioCompressionFormat StreamAudioCompressionFormat; -} XnPackedStreamProperties; - -typedef struct XnPackedStreamPropertiesV1 -{ - XnStreamDepthCompressionFormat StreamDepthCompressionFormat; - XnStreamImageCompressionFormat StreamImageCompressionFormat; - XnStreamMiscCompressionFormat StreamMiscCompressionFormat; -} XnPackedStreamPropertiesV1; - -typedef XnPackedStreamPropertiesV1 XnPackedStreamPropertiesV2; - -typedef struct XnPackedStreamFrameHeaderV1 -{ - XnUInt32 nCompDepthBufferSize; - XnUInt32 nCompImageBufferSize; - XnUInt32 nCompMiscBufferSize; -} XnPackedStreamFrameHeaderV1; - -typedef XnPackedStreamFrameHeaderV1 XnPackedStreamFrameHeaderV2; - -typedef struct XnPackedStreamFrameHeaderV3 -{ - XnUInt32 nCompDepthBufferSize; - XnUInt32 nCompImageBufferSize; - XnUInt32 nCompMiscBufferSize; - XnUInt32 nCompAudioBufferSize; -} XnPackedStreamFrameHeaderV3; - -typedef struct XnShift2DepthStruct -{ - /** True if shift-to-depth params are available. */ - XnBool bShift2DepthData; - XnUInt32 nConstShift; - XnUInt32 nPixelSizeFactor; - /** The maximum possible shift value from this device. */ - XnUInt32 nMaxShiftValue; - /** The maximum possible depth from this device (as opposed to a cut-off). */ - XnUInt32 nMaxDepthValue; - XnUInt32 nParamCoeff; - XnUInt32 nShiftScale; -} XnShift2DepthStruct; - -typedef struct XnStreamPropertiesV3 -{ - /** A bit mask of Xiron stream flags. */ - XN_STREAM_FLAGS_TYPE nStreamFlags; - - /** The number of frames in this Xiron stream. */ - XnUInt32 nNumOfFrames; - - /** The number of frames per second. Legal values are: 15-60.*/ - XnUInt8 nDepthFramesPerSecond; - XnUInt8 nImageFramesPerSecond; - - /** Padding. */ - XnUInt16 nReserved; - - /** The depth buffer format. */ - XnStreamDepthFormat DepthFormat; - /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ - XnUInt16 nDepthXRes; - /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ - XnUInt16 nDepthYRes; - /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nDepthBufferSize; - /** The depth buffer element size in bits. */ - XnUInt32 nDepthTypeBitSize; - - /** The minimum depth value in the depth buffer. */ - XnDepthPixel nDepthMinValue; - /** The maximum depth value in the depth buffer. */ - XnDepthPixel nDepthMaxValue; - /** The value that represents no-sample in the depth buffer. */ - XnDepthPixel nDepthNoSampleValue; - /** The value that represents shadow in the depth buffer. */ - XnDepthPixel nDepthShadowValue; - - /** The image buffer format. */ - XnStreamImageFormat ImageFormat; - /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ - XnUInt16 nImageXRes; - /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ - XnUInt16 nImageYRes; - /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nImageBufferSize; - /** The image buffer element size in bits. */ - XnUInt32 nImageTypeBitSize; - - /** The audio buffer format. */ - XnStreamAudioFormat AudioFormat; - /** The number of audio channels. */ - XnUInt8 nAudioNumOfChannels; - - /** Padding. */ - XnUInt8 nReserved2; - XnUInt16 nReserved3; - - /** The audio sample rate. */ - XnSampleRate nAudioSampleRate; - /** The audio buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nAudioBufferSize; - /** Audio read mode. */ - XnAudioReadMode AudioReadMode; - /** When AudioReadMode is XN_AUDIO_READ_STREAM, this member is the number of bytes that will be read each time. */ - XnUInt32 nAudioReadChunkSize; - - /** The miscellaneous buffer format. */ - XnStreamMiscFormat MiscFormat; - /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nMiscBufferSize; - /** The miscellaneous buffer element size in bits. */ - XnUInt32 nMiscTypeBitSize; - - /** The zero plane distance in depth units. */ - XnDepthPixel nZeroPlaneDistance; - - /** Padding. */ - XnUInt16 nReserved4; - - /** The zero plane pixel size */ - XnFloat fZeroPlanePixelSize; - /** The distance between the emitter and the Depth Cmos */ - XnFloat fEmitterDCmosDistance; - - /** Information relevant for Shift2Depth */ - XnShift2DepthStruct Shift2DepthData; - -} XnStreamPropertiesV3; - -#pragma pack (pop) - -typedef struct XnStreamPropertiesV2 -{ - /** A bit mask of Xiron stream flags. */ - XN_STREAM_FLAGS_TYPE nStreamFlags; - - /** The number of frames in this Xiron stream. */ - XnUInt32 nNumOfFrames; - /** The number of frames per second. Legal values are: 15-60.*/ - XnUInt8 nDepthFramesPerSecond; - XnUInt8 nImageFramesPerSecond; - - /** The depth buffer format. */ - XnStreamDepthFormat DepthFormat; - /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ - XnUInt16 nDepthXRes; - /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ - XnUInt16 nDepthYRes; - /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nDepthBufferSize; - /** The depth buffer element size in bits. */ - XnUInt32 nDepthTypeBitSize; - - /** The minimum depth value in the depth buffer. */ - XnDepthPixel nDepthMinValue; - /** The maximum depth value in the depth buffer. */ - XnDepthPixel nDepthMaxValue; - /** The value that represents no-sample in the depth buffer. */ - XnDepthPixel nDepthNoSampleValue; - /** The value that represents shadow in the depth buffer. */ - XnDepthPixel nDepthShadowValue; - - /** The image buffer format. */ - XnStreamImageFormat ImageFormat; - /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ - XnUInt16 nImageXRes; - /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ - XnUInt16 nImageYRes; - /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nImageBufferSize; - /** The image buffer element size in bits. */ - XnUInt32 nImageTypeBitSize; - - /** The miscellaneous buffer format. */ - XnStreamMiscFormat MiscFormat; - /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nMiscBufferSize; - /** The miscellaneous buffer element size in bits. */ - XnUInt32 nMiscTypeBitSize; - - /** The zero plane distance in depth units. */ - XnDepthPixel nZeroPlaneDistance; - /** The zero plane pixel size */ - XnFloat fZeroPlanePixelSize; - /** The distance between the emitter and the Depth Cmos */ - XnFloat fEmitterDCmosDistance; - - /** Information relevant for Shift2Depth */ - struct { - XnBool bShift2DepthData; - XnUInt32 nConstShift; - XnUInt32 nPixelSizeFactor; - XnUInt32 nMaxShiftValue; - XnUInt32 nMaxDepthValue; - XnUInt32 nParamCoeff; - XnUInt32 nShiftScale; - } Shift2DepthData; - -} XnStreamPropertiesV2; - -typedef struct XnStreamPropertiesV1 -{ - /** A bit mask of Xiron stream flags. */ - XN_STREAM_FLAGS_TYPE nStreamFlags; - - /** The number of frames in this Xiron stream. */ - XnUInt32 nNumOfFrames; - /** The number of frames per second. Legal values are: 15-60.*/ - XnUInt8 nFramesPerSecond; - - /** The depth buffer format. */ - XnStreamDepthFormat DepthFormat; - /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ - XnUInt16 nDepthXRes; - /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ - XnUInt16 nDepthYRes; - /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nDepthBufferSize; - /** The depth buffer element size in bits. */ - XnUInt32 nDepthTypeBitSize; - - /** The minimum depth value in the depth buffer. */ - XnDepthPixel nDepthMinValue; - /** The maximum depth value in the depth buffer. */ - XnDepthPixel nDepthMaxValue; - /** The value that represents no-sample in the depth buffer. */ - XnDepthPixel nDepthNoSampleValue; - /** The value that represents shadow in the depth buffer. */ - XnDepthPixel nDepthShadowValue; - - /** The image buffer format. */ - XnStreamImageFormat ImageFormat; - /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ - XnUInt16 nImageXRes; - /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ - XnUInt16 nImageYRes; - /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nImageBufferSize; - /** The image buffer element size in bits. */ - XnUInt32 nImageTypeBitSize; - - /** The miscellaneous buffer format. */ - XnStreamMiscFormat MiscFormat; - /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ - XnUInt32 nMiscBufferSize; - /** The miscellaneous buffer element size in bits. */ - XnUInt32 nMiscTypeBitSize; - - /** The zero plane distance in depth units. */ - XnDepthPixel nZeroPlaneDistance; - /** The zero plane pixel size */ - XnFloat fZeroPlanePixelSize; -} XnStreamPropertiesV1; - -/** - * Describes the Xiron stream frame properties. - * Every single frame of the stream should have one defined. - */ -typedef struct XnStreamFramePropertiesV2 -{ - union - { - /** Backward compatibility - general ID equals the Depth Frame ID */ - XnUInt32 nFrameID; - /** The frame id of this stream frame. */ - XnUInt32 nDepthFrameID; - }; - XnUInt32 nImageFrameID; - - union - { - /** Backward compatibility - general TimeStamp equals the Depth Frame ID */ - XnUInt64 nTimeStamp; - /** The creation time of this stream frame. */ - XnUInt64 nDepthTimeStamp; - }; - - XnUInt64 nImageTimeStamp; -} XnStreamFramePropertiesV2; - -typedef struct XnStreamFramePropertiesV1 -{ - /** The frame id of this stream frame. */ - XnUInt32 nFrameID; - - /** The creation time of this stream frame. */ - XnUInt64 nTimeStamp; -} XnStreamFramePropertiesV1; - -typedef struct XnDeviceFileHeaderV3 -{ - XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; - XnUInt16 nMajorVersion; - XnUInt16 nMinorVersion; - XnStreamProperties StreamProperties; - XnPackedStreamProperties PackedStreamProperties; -} XnDeviceFileHeaderV3; - -typedef struct XnDeviceFileHeaderV2 -{ - XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; - XnStreamPropertiesV2 StreamProperties; - XnPackedStreamPropertiesV2 PackedStreamProperties; -} XnDeviceFileHeaderV2; - -typedef struct XnDeviceFileHeaderV1 -{ - XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; - XnStreamPropertiesV1 StreamProperties; - XnPackedStreamPropertiesV1 PackedStreamProperties; -} XnDeviceFileHeaderV1; - -typedef struct XnDeviceFileFrameHeaderV3 -{ - XnUInt32 nPackedStreamSize; - XnUInt32 nReserved; - XnStreamFrameProperties FrameProperties; -} XnDeviceFileFrameHeaderV3; - -typedef struct XnDeviceFileFrameHeaderV2 -{ - XnUInt32 nPackedStreamSize; - XnStreamFramePropertiesV2 FrameProperties; -} XnDeviceFileFrameHeaderV2; - -typedef struct XnDeviceFileFrameHeaderV1 -{ - XnUInt32 nPackedStreamSize; - XnStreamFramePropertiesV1 FrameProperties; -} XnDeviceFileFrameHeaderV1; - -typedef struct XnFileBCData -{ - XN_FILE_HANDLE FileHandle; - - XnUInt32 nFramePos; - - XnPackedStreamProperties PackedStreamProperties; - XnUInt8* pPackedStreamBuffer; - XnUInt32 nPackedStreamBufferSize; - - XnStreamPropertiesV3 StreamProperties; -} XnFileBCData; - -typedef struct XnDeviceFileHeader -{ - XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; - XnUInt16 nMajorVersion; - XnUInt16 nMinorVersion; - XnStreamProperties StreamProperties; - XnPackedStreamProperties PackedStreamProperties; -} XnDeviceFileHeader; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_DEVICE_FILE_READER_BC_H_ +#define _XN_DEVICE_FILE_READER_BC_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceFile.h" + +#define _XN_IO_BC +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +#pragma pack (push, 1) + +typedef struct XnPackedStreamProperties +{ + XnStreamDepthCompressionFormat StreamDepthCompressionFormat; + XnStreamImageCompressionFormat StreamImageCompressionFormat; + XnStreamMiscCompressionFormat StreamMiscCompressionFormat; + XnStreamAudioCompressionFormat StreamAudioCompressionFormat; +} XnPackedStreamProperties; + +typedef struct XnPackedStreamPropertiesV1 +{ + XnStreamDepthCompressionFormat StreamDepthCompressionFormat; + XnStreamImageCompressionFormat StreamImageCompressionFormat; + XnStreamMiscCompressionFormat StreamMiscCompressionFormat; +} XnPackedStreamPropertiesV1; + +typedef XnPackedStreamPropertiesV1 XnPackedStreamPropertiesV2; + +typedef struct XnPackedStreamFrameHeaderV1 +{ + XnUInt32 nCompDepthBufferSize; + XnUInt32 nCompImageBufferSize; + XnUInt32 nCompMiscBufferSize; +} XnPackedStreamFrameHeaderV1; + +typedef XnPackedStreamFrameHeaderV1 XnPackedStreamFrameHeaderV2; + +typedef struct XnPackedStreamFrameHeaderV3 +{ + XnUInt32 nCompDepthBufferSize; + XnUInt32 nCompImageBufferSize; + XnUInt32 nCompMiscBufferSize; + XnUInt32 nCompAudioBufferSize; +} XnPackedStreamFrameHeaderV3; + +typedef struct XnShift2DepthStruct +{ + /** True if shift-to-depth params are available. */ + XnBool bShift2DepthData; + XnUInt32 nConstShift; + XnUInt32 nPixelSizeFactor; + /** The maximum possible shift value from this device. */ + XnUInt32 nMaxShiftValue; + /** The maximum possible depth from this device (as opposed to a cut-off). */ + XnUInt32 nMaxDepthValue; + XnUInt32 nParamCoeff; + XnUInt32 nShiftScale; +} XnShift2DepthStruct; + +typedef struct XnStreamPropertiesV3 +{ + /** A bit mask of Xiron stream flags. */ + XN_STREAM_FLAGS_TYPE nStreamFlags; + + /** The number of frames in this Xiron stream. */ + XnUInt32 nNumOfFrames; + + /** The number of frames per second. Legal values are: 15-60.*/ + XnUInt8 nDepthFramesPerSecond; + XnUInt8 nImageFramesPerSecond; + + /** Padding. */ + XnUInt16 nReserved; + + /** The depth buffer format. */ + XnStreamDepthFormat DepthFormat; + /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ + XnUInt16 nDepthXRes; + /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ + XnUInt16 nDepthYRes; + /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nDepthBufferSize; + /** The depth buffer element size in bits. */ + XnUInt32 nDepthTypeBitSize; + + /** The minimum depth value in the depth buffer. */ + XnDepthPixel nDepthMinValue; + /** The maximum depth value in the depth buffer. */ + XnDepthPixel nDepthMaxValue; + /** The value that represents no-sample in the depth buffer. */ + XnDepthPixel nDepthNoSampleValue; + /** The value that represents shadow in the depth buffer. */ + XnDepthPixel nDepthShadowValue; + + /** The image buffer format. */ + XnStreamImageFormat ImageFormat; + /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ + XnUInt16 nImageXRes; + /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ + XnUInt16 nImageYRes; + /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nImageBufferSize; + /** The image buffer element size in bits. */ + XnUInt32 nImageTypeBitSize; + + /** The audio buffer format. */ + XnStreamAudioFormat AudioFormat; + /** The number of audio channels. */ + XnUInt8 nAudioNumOfChannels; + + /** Padding. */ + XnUInt8 nReserved2; + XnUInt16 nReserved3; + + /** The audio sample rate. */ + XnSampleRate nAudioSampleRate; + /** The audio buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nAudioBufferSize; + /** Audio read mode. */ + XnAudioReadMode AudioReadMode; + /** When AudioReadMode is XN_AUDIO_READ_STREAM, this member is the number of bytes that will be read each time. */ + XnUInt32 nAudioReadChunkSize; + + /** The miscellaneous buffer format. */ + XnStreamMiscFormat MiscFormat; + /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nMiscBufferSize; + /** The miscellaneous buffer element size in bits. */ + XnUInt32 nMiscTypeBitSize; + + /** The zero plane distance in depth units. */ + XnDepthPixel nZeroPlaneDistance; + + /** Padding. */ + XnUInt16 nReserved4; + + /** The zero plane pixel size */ + XnFloat fZeroPlanePixelSize; + /** The distance between the emitter and the Depth Cmos */ + XnFloat fEmitterDCmosDistance; + + /** Information relevant for Shift2Depth */ + XnShift2DepthStruct Shift2DepthData; + +} XnStreamPropertiesV3; + +#pragma pack (pop) + +typedef struct XnStreamPropertiesV2 +{ + /** A bit mask of Xiron stream flags. */ + XN_STREAM_FLAGS_TYPE nStreamFlags; + + /** The number of frames in this Xiron stream. */ + XnUInt32 nNumOfFrames; + /** The number of frames per second. Legal values are: 15-60.*/ + XnUInt8 nDepthFramesPerSecond; + XnUInt8 nImageFramesPerSecond; + + /** The depth buffer format. */ + XnStreamDepthFormat DepthFormat; + /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ + XnUInt16 nDepthXRes; + /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ + XnUInt16 nDepthYRes; + /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nDepthBufferSize; + /** The depth buffer element size in bits. */ + XnUInt32 nDepthTypeBitSize; + + /** The minimum depth value in the depth buffer. */ + XnDepthPixel nDepthMinValue; + /** The maximum depth value in the depth buffer. */ + XnDepthPixel nDepthMaxValue; + /** The value that represents no-sample in the depth buffer. */ + XnDepthPixel nDepthNoSampleValue; + /** The value that represents shadow in the depth buffer. */ + XnDepthPixel nDepthShadowValue; + + /** The image buffer format. */ + XnStreamImageFormat ImageFormat; + /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ + XnUInt16 nImageXRes; + /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ + XnUInt16 nImageYRes; + /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nImageBufferSize; + /** The image buffer element size in bits. */ + XnUInt32 nImageTypeBitSize; + + /** The miscellaneous buffer format. */ + XnStreamMiscFormat MiscFormat; + /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nMiscBufferSize; + /** The miscellaneous buffer element size in bits. */ + XnUInt32 nMiscTypeBitSize; + + /** The zero plane distance in depth units. */ + XnDepthPixel nZeroPlaneDistance; + /** The zero plane pixel size */ + XnFloat fZeroPlanePixelSize; + /** The distance between the emitter and the Depth Cmos */ + XnFloat fEmitterDCmosDistance; + + /** Information relevant for Shift2Depth */ + struct { + XnBool bShift2DepthData; + XnUInt32 nConstShift; + XnUInt32 nPixelSizeFactor; + XnUInt32 nMaxShiftValue; + XnUInt32 nMaxDepthValue; + XnUInt32 nParamCoeff; + XnUInt32 nShiftScale; + } Shift2DepthData; + +} XnStreamPropertiesV2; + +typedef struct XnStreamPropertiesV1 +{ + /** A bit mask of Xiron stream flags. */ + XN_STREAM_FLAGS_TYPE nStreamFlags; + + /** The number of frames in this Xiron stream. */ + XnUInt32 nNumOfFrames; + /** The number of frames per second. Legal values are: 15-60.*/ + XnUInt8 nFramesPerSecond; + + /** The depth buffer format. */ + XnStreamDepthFormat DepthFormat; + /** The depth X resolution. Legal values are: 160-640 and must be a multiple of 4. */ + XnUInt16 nDepthXRes; + /** The depth Y resolution. Legal values are: 120-512 and must be a multiple of 4. */ + XnUInt16 nDepthYRes; + /** The depth buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nDepthBufferSize; + /** The depth buffer element size in bits. */ + XnUInt32 nDepthTypeBitSize; + + /** The minimum depth value in the depth buffer. */ + XnDepthPixel nDepthMinValue; + /** The maximum depth value in the depth buffer. */ + XnDepthPixel nDepthMaxValue; + /** The value that represents no-sample in the depth buffer. */ + XnDepthPixel nDepthNoSampleValue; + /** The value that represents shadow in the depth buffer. */ + XnDepthPixel nDepthShadowValue; + + /** The image buffer format. */ + XnStreamImageFormat ImageFormat; + /** The image X resolution. Legal values are: 160-640 and must be a multiply of 4. */ + XnUInt16 nImageXRes; + /** The image Y resolution. Legal values are: 120-512 and must be a multiply of 4. */ + XnUInt16 nImageYRes; + /** The image buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nImageBufferSize; + /** The image buffer element size in bits. */ + XnUInt32 nImageTypeBitSize; + + /** The miscellaneous buffer format. */ + XnStreamMiscFormat MiscFormat; + /** The miscellaneous buffer size in bytes. OpenDevice will automatically update this field to the correct size.*/ + XnUInt32 nMiscBufferSize; + /** The miscellaneous buffer element size in bits. */ + XnUInt32 nMiscTypeBitSize; + + /** The zero plane distance in depth units. */ + XnDepthPixel nZeroPlaneDistance; + /** The zero plane pixel size */ + XnFloat fZeroPlanePixelSize; +} XnStreamPropertiesV1; + +/** + * Describes the Xiron stream frame properties. + * Every single frame of the stream should have one defined. + */ +typedef struct XnStreamFramePropertiesV2 +{ + union + { + /** Backward compatibility - general ID equals the Depth Frame ID */ + XnUInt32 nFrameID; + /** The frame id of this stream frame. */ + XnUInt32 nDepthFrameID; + }; + XnUInt32 nImageFrameID; + + union + { + /** Backward compatibility - general TimeStamp equals the Depth Frame ID */ + XnUInt64 nTimeStamp; + /** The creation time of this stream frame. */ + XnUInt64 nDepthTimeStamp; + }; + + XnUInt64 nImageTimeStamp; +} XnStreamFramePropertiesV2; + +typedef struct XnStreamFramePropertiesV1 +{ + /** The frame id of this stream frame. */ + XnUInt32 nFrameID; + + /** The creation time of this stream frame. */ + XnUInt64 nTimeStamp; +} XnStreamFramePropertiesV1; + +typedef struct XnDeviceFileHeaderV3 +{ + XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; + XnUInt16 nMajorVersion; + XnUInt16 nMinorVersion; + XnStreamProperties StreamProperties; + XnPackedStreamProperties PackedStreamProperties; +} XnDeviceFileHeaderV3; + +typedef struct XnDeviceFileHeaderV2 +{ + XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; + XnStreamPropertiesV2 StreamProperties; + XnPackedStreamPropertiesV2 PackedStreamProperties; +} XnDeviceFileHeaderV2; + +typedef struct XnDeviceFileHeaderV1 +{ + XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; + XnStreamPropertiesV1 StreamProperties; + XnPackedStreamPropertiesV1 PackedStreamProperties; +} XnDeviceFileHeaderV1; + +typedef struct XnDeviceFileFrameHeaderV3 +{ + XnUInt32 nPackedStreamSize; + XnUInt32 nReserved; + XnStreamFrameProperties FrameProperties; +} XnDeviceFileFrameHeaderV3; + +typedef struct XnDeviceFileFrameHeaderV2 +{ + XnUInt32 nPackedStreamSize; + XnStreamFramePropertiesV2 FrameProperties; +} XnDeviceFileFrameHeaderV2; + +typedef struct XnDeviceFileFrameHeaderV1 +{ + XnUInt32 nPackedStreamSize; + XnStreamFramePropertiesV1 FrameProperties; +} XnDeviceFileFrameHeaderV1; + +typedef struct XnFileBCData +{ + XN_FILE_HANDLE FileHandle; + + XnUInt32 nFramePos; + + XnPackedStreamProperties PackedStreamProperties; + XnUInt8* pPackedStreamBuffer; + XnUInt32 nPackedStreamBufferSize; + + XnStreamPropertiesV3 StreamProperties; +} XnFileBCData; + +typedef struct XnDeviceFileHeader +{ + XnChar cpMagic[XN_DEVICE_FILE_MAGIC_LEN]; + XnUInt16 nMajorVersion; + XnUInt16 nMinorVersion; + XnStreamProperties StreamProperties; + XnPackedStreamProperties PackedStreamProperties; +} XnDeviceFileHeader; + #endif //_XN_DEVICE_FILE_READER_BC_H_ \ No newline at end of file diff --git a/Source/XnDeviceFile/XnDeviceFileWriter.cpp b/Source/XnDeviceFile/XnDeviceFileWriter.cpp index d1ae22a..2bfd31f 100644 --- a/Source/XnDeviceFile/XnDeviceFileWriter.cpp +++ b/Source/XnDeviceFile/XnDeviceFileWriter.cpp @@ -1,262 +1,262 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceFileWriter.h" -#include -#include -#include "XnDeviceFile.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDeviceFileWriter::XnDeviceFileWriter() : - XnStreamWriterDevice(XN_DEVICE_NAME, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER), - m_bTimerStarted(FALSE) -{ -} - -XnDeviceFileWriter::~XnDeviceFileWriter() -{ -} - -XnStatus XnDeviceFileWriter::Destroy() -{ - if (m_bTimerStarted) - { - xnOSStopTimer(&m_Timer); - m_bTimerStarted = FALSE; - } - - return XnStreamWriterDevice::Destroy(); -} - -XnStatus XnDeviceFileWriter::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create stream using base (this will also write it down to the file) - nRetVal = XnStreamWriterDevice::CreateStream(StreamType, StreamName, pInitialValues); - XN_IS_STATUS_OK(nRetVal); - - // now, we leave a place for a property change - the number of frames. We will update this - // property once the stream is closed. - XnFileWriterStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - nRetVal = GetIOStream()->Tell(&pStream->m_nNumFramesPos); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->WriteProperty(StreamName, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, 0ULL); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileWriter::DestroyStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // before closing this stream, we want to write down how many frames were written - XnFileWriterStream* pStream; - nRetVal = FindStream(StreamName, &pStream); - XN_IS_STATUS_OK(nRetVal); - - XnUInt32 nCurPos; - nRetVal = GetIOStream()->Tell(&nCurPos); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetIOStream()->Seek(pStream->m_nNumFramesPos); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetDataPacker()->WriteProperty(StreamName, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, pStream->GetNumberOfFrames()); - XN_IS_STATUS_OK(nRetVal); - - // now seek back - nRetVal = GetIOStream()->Seek(nCurPos); - XN_IS_STATUS_OK(nRetVal); - - // and destroy it - nRetVal = XnStreamWriterDevice::DestroyStream(StreamName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileWriter::WriteStream(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // start the timer on the first data written - nRetVal = StartTimer(); - XN_IS_STATUS_OK(nRetVal); - - // fill in timestamp if needed - if (pStreamOutput->nTimestamp == 0) - { - XnUInt64 nNow; - xnOSQueryTimer(m_Timer, &nNow); - - if (!IsHighResTimestamps()) - { - nNow /= 1000; - } - - pStreamOutput->nTimestamp = nNow; - } - - // and write it down (using base) - nRetVal = XnStreamWriterDevice::WriteStream(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileWriter::Write(XnStreamDataSet* pStreamOutputSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pStreamOutputSet); - - // get a list of objects in the set - XnStreamData* aOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, aOutputs, &nCount); - XN_IS_STATUS_OK(nRetVal); - - // BC: old applications wrote down all streams every frame, even if no new data. This might - // cause some of the streams to have timestamp 0, while other have a real timestamp. - // In this case, remove these frames. However, we need to check - if all timestamps - // are 0, then we'll fill it up by ourselves. - XnBool bSomeHasTimestamps = FALSE; - - for (XnUInt32 i = 0; i < nCount; ++i) - { - if (aOutputs[i]->nTimestamp != 0) - { - bSomeHasTimestamps = TRUE; - break; - } - } - - if (bSomeHasTimestamps) - { - // remove all the ones with zero timestamp - for (XnUInt32 i = 0; i < nCount; ++i) - { - if (aOutputs[i]->nTimestamp == 0) - { - aOutputs[i]->bIsNew = FALSE; - } - } - } - - // OK. write it down using base - nRetVal = XnStreamWriterDevice::Write(pStreamOutputSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileWriter::StartTimer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bTimerStarted) - { - nRetVal = xnOSStartHighResTimer(&m_Timer); - XN_IS_STATUS_OK(nRetVal); - - m_bTimerStarted = TRUE; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceFileWriter::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnFileWriterStream* pStream; - XN_VALIDATE_NEW(pStream, XnFileWriterStream, StreamType, StreamName, GetDataPacker()); - - XnStreamDeviceStreamHolder* pHolder = XN_NEW(XnStreamDeviceStreamHolder, pStream, FALSE); - if (pHolder == NULL) - { - XN_DELETE(pStream); - return XN_STATUS_ALLOC_FAILED; - } - - *ppStreamHolder = pHolder; - - return (XN_STATUS_OK); -} - -void XnDeviceFileWriter::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) -{ - XN_DELETE(pStreamHolder->GetModule()); - XN_DELETE(pStreamHolder); -} - -XnStatus XnDeviceFileWriter::CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_NEW_AND_INIT(pStream, XnIOFileStream, strConnectionString, XN_OS_FILE_WRITE | XN_OS_FILE_TRUNCATE); - - // write down the magic - nRetVal = pStream->WriteData((const XnUChar*)XN_DEVICE_FILE_MAGIC_V4, strlen(XN_DEVICE_FILE_MAGIC_V4)); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pStream); - pStream = NULL; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -void XnDeviceFileWriter::DestroyIOStreamImpl(XnIOStream* pStream) -{ - pStream->Free(); - XN_DELETE(pStream); -} - -XnStatus XnDeviceFileWriter::FindStream(const XnChar* strName, XnFileWriterStream** ppStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamDeviceStreamHolder* pHolder = NULL; - nRetVal = XnStreamWriterDevice::FindStream(strName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - *ppStream = (XnFileWriterStream*)pHolder->GetStream(); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceFileWriter.h" +#include +#include +#include "XnDeviceFile.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDeviceFileWriter::XnDeviceFileWriter() : + XnStreamWriterDevice(XN_DEVICE_NAME, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER), + m_bTimerStarted(FALSE) +{ +} + +XnDeviceFileWriter::~XnDeviceFileWriter() +{ +} + +XnStatus XnDeviceFileWriter::Destroy() +{ + if (m_bTimerStarted) + { + xnOSStopTimer(&m_Timer); + m_bTimerStarted = FALSE; + } + + return XnStreamWriterDevice::Destroy(); +} + +XnStatus XnDeviceFileWriter::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // create stream using base (this will also write it down to the file) + nRetVal = XnStreamWriterDevice::CreateStream(StreamType, StreamName, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + // now, we leave a place for a property change - the number of frames. We will update this + // property once the stream is closed. + XnFileWriterStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + nRetVal = GetIOStream()->Tell(&pStream->m_nNumFramesPos); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->WriteProperty(StreamName, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, 0ULL); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileWriter::DestroyStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // before closing this stream, we want to write down how many frames were written + XnFileWriterStream* pStream; + nRetVal = FindStream(StreamName, &pStream); + XN_IS_STATUS_OK(nRetVal); + + XnUInt32 nCurPos; + nRetVal = GetIOStream()->Tell(&nCurPos); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetIOStream()->Seek(pStream->m_nNumFramesPos); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetDataPacker()->WriteProperty(StreamName, XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, pStream->GetNumberOfFrames()); + XN_IS_STATUS_OK(nRetVal); + + // now seek back + nRetVal = GetIOStream()->Seek(nCurPos); + XN_IS_STATUS_OK(nRetVal); + + // and destroy it + nRetVal = XnStreamWriterDevice::DestroyStream(StreamName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileWriter::WriteStream(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // start the timer on the first data written + nRetVal = StartTimer(); + XN_IS_STATUS_OK(nRetVal); + + // fill in timestamp if needed + if (pStreamOutput->nTimestamp == 0) + { + XnUInt64 nNow; + xnOSQueryTimer(m_Timer, &nNow); + + if (!IsHighResTimestamps()) + { + nNow /= 1000; + } + + pStreamOutput->nTimestamp = nNow; + } + + // and write it down (using base) + nRetVal = XnStreamWriterDevice::WriteStream(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileWriter::Write(XnStreamDataSet* pStreamOutputSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pStreamOutputSet); + + // get a list of objects in the set + XnStreamData* aOutputs[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + nRetVal = XnStreamDataSetCopyToArray(pStreamOutputSet, aOutputs, &nCount); + XN_IS_STATUS_OK(nRetVal); + + // BC: old applications wrote down all streams every frame, even if no new data. This might + // cause some of the streams to have timestamp 0, while other have a real timestamp. + // In this case, remove these frames. However, we need to check - if all timestamps + // are 0, then we'll fill it up by ourselves. + XnBool bSomeHasTimestamps = FALSE; + + for (XnUInt32 i = 0; i < nCount; ++i) + { + if (aOutputs[i]->nTimestamp != 0) + { + bSomeHasTimestamps = TRUE; + break; + } + } + + if (bSomeHasTimestamps) + { + // remove all the ones with zero timestamp + for (XnUInt32 i = 0; i < nCount; ++i) + { + if (aOutputs[i]->nTimestamp == 0) + { + aOutputs[i]->bIsNew = FALSE; + } + } + } + + // OK. write it down using base + nRetVal = XnStreamWriterDevice::Write(pStreamOutputSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileWriter::StartTimer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bTimerStarted) + { + nRetVal = xnOSStartHighResTimer(&m_Timer); + XN_IS_STATUS_OK(nRetVal); + + m_bTimerStarted = TRUE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceFileWriter::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnFileWriterStream* pStream; + XN_VALIDATE_NEW(pStream, XnFileWriterStream, StreamType, StreamName, GetDataPacker()); + + XnStreamDeviceStreamHolder* pHolder = XN_NEW(XnStreamDeviceStreamHolder, pStream, FALSE); + if (pHolder == NULL) + { + XN_DELETE(pStream); + return XN_STATUS_ALLOC_FAILED; + } + + *ppStreamHolder = pHolder; + + return (XN_STATUS_OK); +} + +void XnDeviceFileWriter::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) +{ + XN_DELETE(pStreamHolder->GetModule()); + XN_DELETE(pStreamHolder); +} + +XnStatus XnDeviceFileWriter::CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_NEW_AND_INIT(pStream, XnIOFileStream, strConnectionString, XN_OS_FILE_WRITE | XN_OS_FILE_TRUNCATE); + + // write down the magic + nRetVal = pStream->WriteData((const XnUChar*)XN_DEVICE_FILE_MAGIC_V4, strlen(XN_DEVICE_FILE_MAGIC_V4)); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pStream); + pStream = NULL; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +void XnDeviceFileWriter::DestroyIOStreamImpl(XnIOStream* pStream) +{ + pStream->Free(); + XN_DELETE(pStream); +} + +XnStatus XnDeviceFileWriter::FindStream(const XnChar* strName, XnFileWriterStream** ppStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamDeviceStreamHolder* pHolder = NULL; + nRetVal = XnStreamWriterDevice::FindStream(strName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + *ppStream = (XnFileWriterStream*)pHolder->GetStream(); + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceFile/XnDeviceFileWriter.h b/Source/XnDeviceFile/XnDeviceFileWriter.h index ff8acda..ae059b7 100644 --- a/Source/XnDeviceFile/XnDeviceFileWriter.h +++ b/Source/XnDeviceFile/XnDeviceFileWriter.h @@ -1,78 +1,78 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef _XN_DEVICE_FILE_WRITER_H_ -#define _XN_DEVICE_FILE_WRITER_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnFileWriterStream.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnDeviceFileWriter : public XnStreamWriterDevice -{ -public: - XnDeviceFileWriter(); - ~XnDeviceFileWriter(); - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - virtual XnStatus Destroy(); - virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); - virtual XnStatus DestroyStream(const XnChar* StreamName); - virtual XnStatus WriteStream(XnStreamData* pStreamOutput); - virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet); - -protected: - //--------------------------------------------------------------------------- - // Helper Methods - //--------------------------------------------------------------------------- - inline XnIOFileStream* GetIOStream() { return (XnIOFileStream*)XnStreamWriterDevice::GetIOStream(); } - XnStatus FindStream(const XnChar* strName, XnFileWriterStream** ppStream); - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); - void DestroyIOStreamImpl(XnIOStream* pStream); - XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); - void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); - -private: - XnStatus StartTimer(); - - XnOSTimer m_Timer; - XnBool m_bTimerStarted; -}; - -#endif //_XN_DEVICE_FILE_WRITER_H_ - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef _XN_DEVICE_FILE_WRITER_H_ +#define _XN_DEVICE_FILE_WRITER_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnFileWriterStream.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnDeviceFileWriter : public XnStreamWriterDevice +{ +public: + XnDeviceFileWriter(); + ~XnDeviceFileWriter(); + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + virtual XnStatus Destroy(); + virtual XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); + virtual XnStatus DestroyStream(const XnChar* StreamName); + virtual XnStatus WriteStream(XnStreamData* pStreamOutput); + virtual XnStatus Write(XnStreamDataSet* pStreamOutputSet); + +protected: + //--------------------------------------------------------------------------- + // Helper Methods + //--------------------------------------------------------------------------- + inline XnIOFileStream* GetIOStream() { return (XnIOFileStream*)XnStreamWriterDevice::GetIOStream(); } + XnStatus FindStream(const XnChar* strName, XnFileWriterStream** ppStream); + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); + void DestroyIOStreamImpl(XnIOStream* pStream); + XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); + void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); + +private: + XnStatus StartTimer(); + + XnOSTimer m_Timer; + XnBool m_bTimerStarted; +}; + +#endif //_XN_DEVICE_FILE_WRITER_H_ + diff --git a/Source/XnDeviceFile/XnExportedFileDevice.cpp b/Source/XnDeviceFile/XnExportedFileDevice.cpp index b03d4f5..95611d2 100644 --- a/Source/XnDeviceFile/XnExportedFileDevice.cpp +++ b/Source/XnDeviceFile/XnExportedFileDevice.cpp @@ -1,95 +1,95 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnExportedFileDevice.h" -#include -#include "XnDeviceFileReader.h" -#include "XnFileDevice.h" -#include -#include - -//--------------------------------------------------------------------------- -// XnExportedFileDevice class -//--------------------------------------------------------------------------- -void XnExportedFileDevice::FillCommonDescriptionFields(XnProductionNodeDescription* pDescription) -{ - strcpy(pDescription->strName, XN_DEVICE_NAME); - strcpy(pDescription->strVendor, XN_VENDOR_PRIMESENSE); - - pDescription->Version.nMajor = XN_MAJOR_VERSION; - pDescription->Version.nMinor = XN_MINOR_VERSION; - pDescription->Version.nMaintenance = XN_MAINTENANCE_VERSION; - pDescription->Version.nBuild = XN_BUILD_VERSION; -} - -void XnExportedFileDevice::GetDescription(XnProductionNodeDescription* pDescription) -{ - FillCommonDescriptionFields(pDescription); - pDescription->Type = XN_NODE_TYPE_PLAYER; -} - -XnStatus XnExportedFileDevice::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProductionNodeDescription Description; - GetDescription(&Description); - nRetVal = TreesList.Add(Description, NULL, NULL); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnExportedFileDevice::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnFileDevice* pDevice = XN_NEW(XnFileDevice, context, strInstanceName); - if (pDevice == NULL) - { - return (XN_STATUS_ALLOC_FAILED); - } - - nRetVal = pDevice->Init(); - if (nRetVal != XN_STATUS_OK) - { - return (nRetVal); - } - - *ppInstance = pDevice; - - return (XN_STATUS_OK); -} - -void XnExportedFileDevice::Destroy(xn::ModuleProductionNode* pInstance) -{ - XN_DELETE(pInstance); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnExportedFileDevice.h" +#include +#include "XnDeviceFileReader.h" +#include "XnFileDevice.h" +#include +#include + +//--------------------------------------------------------------------------- +// XnExportedFileDevice class +//--------------------------------------------------------------------------- +void XnExportedFileDevice::FillCommonDescriptionFields(XnProductionNodeDescription* pDescription) +{ + strcpy(pDescription->strName, XN_DEVICE_NAME); + strcpy(pDescription->strVendor, XN_VENDOR_PRIMESENSE); + + pDescription->Version.nMajor = XN_MAJOR_VERSION; + pDescription->Version.nMinor = XN_MINOR_VERSION; + pDescription->Version.nMaintenance = XN_MAINTENANCE_VERSION; + pDescription->Version.nBuild = XN_BUILD_VERSION; +} + +void XnExportedFileDevice::GetDescription(XnProductionNodeDescription* pDescription) +{ + FillCommonDescriptionFields(pDescription); + pDescription->Type = XN_NODE_TYPE_PLAYER; +} + +XnStatus XnExportedFileDevice::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProductionNodeDescription Description; + GetDescription(&Description); + nRetVal = TreesList.Add(Description, NULL, NULL); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnExportedFileDevice::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnFileDevice* pDevice = XN_NEW(XnFileDevice, context, strInstanceName); + if (pDevice == NULL) + { + return (XN_STATUS_ALLOC_FAILED); + } + + nRetVal = pDevice->Init(); + if (nRetVal != XN_STATUS_OK) + { + return (nRetVal); + } + + *ppInstance = pDevice; + + return (XN_STATUS_OK); +} + +void XnExportedFileDevice::Destroy(xn::ModuleProductionNode* pInstance) +{ + XN_DELETE(pInstance); +} + diff --git a/Source/XnDeviceFile/XnExportedFileDevice.h b/Source/XnDeviceFile/XnExportedFileDevice.h index 23d116d..c644701 100644 --- a/Source/XnDeviceFile/XnExportedFileDevice.h +++ b/Source/XnDeviceFile/XnExportedFileDevice.h @@ -1,50 +1,50 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_EXPORTED_SENSOR_DEVICE_H__ -#define __XN_EXPORTED_SENSOR_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnDeviceFileReader.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnExportedFileDevice : public xn::ModuleExportedProductionNode -{ -public: - static void FillCommonDescriptionFields(XnProductionNodeDescription* pDescription); - void GetDescription(XnProductionNodeDescription* pDescription); - XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); - XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); - void Destroy(xn::ModuleProductionNode* pInstance); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_EXPORTED_SENSOR_DEVICE_H__ +#define __XN_EXPORTED_SENSOR_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnDeviceFileReader.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnExportedFileDevice : public xn::ModuleExportedProductionNode +{ +public: + static void FillCommonDescriptionFields(XnProductionNodeDescription* pDescription); + void GetDescription(XnProductionNodeDescription* pDescription); + XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); + XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); + void Destroy(xn::ModuleProductionNode* pInstance); +}; + #endif // __XN_EXPORTED_SENSOR_DEVICE_H__ \ No newline at end of file diff --git a/Source/XnDeviceFile/XnFileDevice.cpp b/Source/XnDeviceFile/XnFileDevice.cpp index 6f9e15a..220a392 100644 --- a/Source/XnDeviceFile/XnFileDevice.cpp +++ b/Source/XnDeviceFile/XnFileDevice.cpp @@ -1,1574 +1,1574 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFileDevice.h" -#include -#include -#include -#include "XnDeviceFileReaderBC.h" -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE (1600 * 1200 * sizeof(XnRGB24Pixel)) - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnLastStreamData -{ - XnUInt32 nPosition; - XnUInt32 nFrameID; - XnUInt64 nTimestamp; -} XnLastStreamData; - -XN_DECLARE_STRINGS_HASH(XnLastStreamData, XnLastStreamDataHash); - -//--------------------------------------------------------------------------- -// XnFileDevice class -//--------------------------------------------------------------------------- -XnFileDevice::XnFileDevice(xn::Context& context, const XnChar* strInstanceName) : - m_context(context), - m_pInputStream(NULL), - m_pDataPacker(NULL), - m_pNotifications(NULL), - m_pNotificationsCookie(NULL), - m_bHighresTimestamps(FALSE), - m_pStreamData(NULL), - m_bFileHasData(FALSE), - m_bNodeCollectionChanged(FALSE), - m_nCurrTimestamp(0), - m_pBCData(NULL), - m_bRepeat(TRUE), - m_bEOF(FALSE) -{ - xnOSMemSet(&m_ShiftToDepth, 0, sizeof(m_ShiftToDepth)); -} - -XnFileDevice::~XnFileDevice() -{ - Free(); -} - -XnStatus XnFileDevice::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamDataCreate(&m_pStreamData, "", XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnFileDevice::Free() -{ - for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) - { - XnNodeInfo& nodeInfo = it.Value(); - XN_DELETE(nodeInfo.pXnCodec); - } - m_nodeInfoMap.Clear(); - - if (m_ShiftToDepth.bIsInitialized) - { - XnShiftToDepthFree(&m_ShiftToDepth); - } - - if (m_pInputStream != NULL) - { - XN_DELETE(m_pInputStream); - m_pInputStream = NULL; - } - - if (m_pDataPacker != NULL) - { - m_pDataPacker->Free(); - XN_DELETE(m_pDataPacker); - m_pDataPacker = NULL; - } - - if (m_pStreamData != NULL) - { - XnStreamDataDestroy(&m_pStreamData); - m_pStreamData = NULL; - } -} - -XnStatus XnFileDevice::ReadFileVersion() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read magic from file - XnChar csFileMagic[XN_DEVICE_FILE_MAGIC_LEN]; - nRetVal = m_pInputStream->ReadData((XnUChar*)csFileMagic, XN_DEVICE_FILE_MAGIC_LEN); - XN_IS_STATUS_OK(nRetVal); - - if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V4, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 4; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V3, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 3; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V2, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 2; - } - else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V1, XN_DEVICE_FILE_MAGIC_LEN) == 0) - { - m_nFileVersion = 1; - } - else - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "Invalid file magic!"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadInitialState(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_nFileVersion < 4) - { - if (m_pBCData == NULL) - { - nRetVal = BCInit(); - XN_IS_STATUS_OK(nRetVal); - } - - return BCReadInitialState(pSet); - } - - // read an object from data packer - XnPackedDataType nType; - nRetVal = m_pDataPacker->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType != XN_PACKED_PROPERTY_SET) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Stream does not start with a property set!"); - } - - nRetVal = m_pDataPacker->ReadPropertySet(pSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SetInitialState(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Fix state (remove some properties that we don't wish to reflect in reader device) - XnActualPropertiesHash* pDeviceModule = NULL; - if (XN_STATUS_OK == pSet->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModule)) - { - pDeviceModule->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); - pDeviceModule->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); - - // check for timestamps resolution - XnActualIntProperty* pIntProp; - if (XN_STATUS_OK == pDeviceModule->Get(XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, (XnProperty*&)pIntProp)) - { - m_bHighresTimestamps = (pIntProp->GetValue() == TRUE); - } - } - - // TODO: create DEVICE node - - // now create the rest of the modules and streams (DEVICE was already created) - XnPropertySetData* pPropSetData = pSet->pData; - for (XnPropertySetData::ConstIterator it = pPropSetData->begin(); it != pPropSetData->end(); ++it) - { - // ignore module DEVICE - if (strcmp(XN_MODULE_NAME_DEVICE, it.Key()) == 0) - { - continue; - } - - // check if this is a stream - XnActualPropertiesHash::ConstIterator itProp = it.Value()->end(); - if (XN_STATUS_OK == it.Value()->Find(XN_STREAM_PROPERTY_TYPE, itProp)) - { - XnActualStringProperty* pTypeProp = (XnActualStringProperty*)itProp.Value(); - nRetVal = HandleNewStream(pTypeProp->GetValue(), it.Key(), it.Value()); - XN_IS_STATUS_OK(nRetVal); - } - } // modules loop - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SetInputStream(void *pStreamCookie, XnPlayerInputStreamInterface *pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_NEW(m_pInputStream, XnInputStream, pStream, pStreamCookie); - - nRetVal = m_pInputStream->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(m_pInputStream); - return (nRetVal); - } - - // read format version - nRetVal = ReadFileVersion(); - XN_IS_STATUS_OK(nRetVal); - - m_pDataPacker = XN_NEW(XnDataPacker, m_pInputStream, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER); - if (m_pDataPacker == NULL) - { - XN_DELETE(m_pInputStream); - return (XN_STATUS_ALLOC_FAILED); - } - - nRetVal = m_pDataPacker->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(m_pDataPacker); - XN_DELETE(m_pInputStream); - return (nRetVal); - } - - // read initial state - XN_PROPERTY_SET_CREATE_ON_STACK(props); - nRetVal = ReadInitialState(&props); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetInitialState(&props); - XN_IS_STATUS_OK(nRetVal); - - // now read till first data - XnBool bWrap; - nRetVal = ReadTillNextData(&bWrap); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SetNodeNotifications(void *pNodeNotificationsCookie, XnNodeNotifications *pNodeNotifications) -{ - m_pNotifications = pNodeNotifications; - m_pNotificationsCookie = pNodeNotificationsCookie; - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SetRepeat(XnBool bRepeat) -{ - m_bRepeat = bRepeat; - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SeekTo(XnUInt64 nMinTimestamp, const XnChar* strNodeName, XnUInt32 nMinFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first check if we need to seek forward or backwards (even if we're in the correct location, - // we need to rewind, so that next read will return this frame again). - XnNodeInfo* pNodeInfo = NULL; - if (strNodeName != NULL) - { - nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - if (nMinFrameID <= pNodeInfo->nCurrFrameID) - { - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - } - } - else - { - if (nMinTimestamp <= m_nCurrTimestamp) - { - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - } - } - - XnBool bFoundNewData = FALSE; - - // Keep current position. - XnUInt32 nStartingPosition; - nRetVal = m_pInputStream->Tell(&nStartingPosition); - XN_IS_STATUS_OK(nRetVal); - - // start seeking forward until point is reached. - XnUInt32 nFoundPosition; - XnPackedDataType nType = (XnPackedDataType)-1; - XnLastStreamDataHash StreamsHash; - - while (TRUE) - { - XnUInt32 nPositionBefore; - nRetVal = m_pInputStream->Tell(&nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pDataPacker->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - XnUInt32 nPositionAfter; - nRetVal = m_pInputStream->Tell(&nPositionAfter); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_STREAM_DATA) - { - bFoundNewData = TRUE; - - XnStreamData props; - XnCompressionFormats nCompression; - XnUInt32 nCompressedSize; - nRetVal = m_pDataPacker->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - XnLastStreamData data; - if (XN_STATUS_OK != StreamsHash.Get(props.StreamName, data)) - { - XnNodeInfo* pNodeInfo; - nRetVal = m_nodeInfoMap.Get(props.StreamName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - data.nFrameID = pNodeInfo->nCurrFrameID + 1; - } - else - { - // if we had previous data from this stream, ignore it - m_PositionsToIgnore.Set(data.nPosition, 0); - - ++data.nFrameID; - } - - data.nPosition = nPositionAfter; - data.nTimestamp = props.nTimestamp; - nRetVal = StreamsHash.Set(props.StreamName, data); - XN_IS_STATUS_OK(nRetVal); - - // now check if condition is met - if (strNodeName != NULL) - { - if (strcmp(strNodeName, props.StreamName) == 0 && - data.nFrameID >= nMinFrameID) - { - // keep this position (we'll read up till here). - nFoundPosition = nPositionAfter; - break; - } - } - else if (data.nTimestamp >= nMinTimestamp) - { - // keep this position (we'll read up till here). - nFoundPosition = nPositionAfter; - break; - } - } - else if (nType == XN_PACKED_END) - { - // we'll read up to the last data of each stream - nFoundPosition = nPositionBefore; - break; - } - } - - // now seek back - nRetVal = m_pInputStream->Seek(nStartingPosition); - XN_IS_STATUS_OK(nRetVal); - - if (bFoundNewData) - { - // read everything up to position - XnUInt32 nPositionAfter = nStartingPosition; - - while (nPositionAfter < nFoundPosition) - { - nRetVal = ReadNextEventFromStream(&nType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pInputStream->Tell(&nPositionAfter); - XN_IS_STATUS_OK(nRetVal); - } - } - else - { -/* // just remark the data as new (this is last frame, return it again to user) - XnDeviceModuleHolderList streams; - nRetVal = GetStreamsList(streams); - XN_IS_STATUS_OK(nRetVal); - - for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) - { - XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); - pStream->ReMarkDataAsNew(); - } -*/ } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::SeekToTimeStamp(XnInt64 nTimeOffset, XnPlayerSeekOrigin origin) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nTimestamp = 0; - if (origin == XN_PLAYER_SEEK_CUR) - { - nTimestamp = m_nCurrTimestamp + nTimeOffset; - } - else if (origin == XN_PLAYER_SEEK_SET) - { - nTimestamp = nTimeOffset; - } - else - { - // TODO: find max timestamp and add offset - return XN_STATUS_NOT_IMPLEMENTED; - } - - xnLogInfo(XN_MASK_FILE, "Seeking file to timestamp %llu...", nTimestamp); - - if (m_nFileVersion < 4) - { - return BCSeek(nTimestamp); - } - else - { - return SeekTo(nTimestamp, NULL, 0); - } -} - -XnStatus XnFileDevice::SeekToFrame(const XnChar* strNodeName, XnInt32 nFrameOffset, XnPlayerSeekOrigin origin) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnNodeInfo* pNodeInfo; - nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - XnInt32 nFrameID = 0; - - switch (origin) - { - case XN_PLAYER_SEEK_CUR: - nFrameID = pNodeInfo->nCurrFrameID + nFrameOffset; - break; - case XN_PLAYER_SEEK_SET: - nFrameID = nFrameOffset; - break; - case XN_PLAYER_SEEK_END: - // TODO: handle - return XN_STATUS_NOT_IMPLEMENTED; - } - - // don't allow seeking to frame 0 - nFrameID = XN_MAX(nFrameID, 1); - - xnLogInfo(XN_MASK_FILE, "Seeking file to frameID %u of node %s...", nFrameID, strNodeName); - - if (m_nFileVersion < 4) - { - return BCSeekFrame(nFrameID); - } - else - { - nRetVal = SeekTo(0, strNodeName, nFrameID); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::TellTimestamp(XnUInt64& nTimestamp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nTimestamp = m_nCurrTimestamp; - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::TellFrame(const XnChar* strNodeName, XnUInt32 &nFrameOffset) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnNodeInfo* pNodeInfo; - nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - nFrameOffset = pNodeInfo->nCurrFrameID; - - return (XN_STATUS_OK); -} - - -XnStatus XnFileDevice::GetNumFrames(const XnChar* strNodeName, XnUInt32& nFrames) -{ - XnStatus nRetVal = XN_STATUS_OK; - xn::ProductionNode node; - nRetVal = m_context.GetProductionNodeByName(strNodeName, node); - XN_IS_STATUS_OK(nRetVal); - XnUInt64 nFrames64 = 0; - nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, nFrames64); - XN_IS_STATUS_OK(nRetVal); - nFrames = (XnUInt32)nFrames64; - - return XN_STATUS_OK; -} - -XnBool XnFileDevice::IsEOF() -{ - return m_bEOF; -} - -XnStatus XnFileDevice::RegisterToEndOfFileReached(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - return m_eofEvent.Register(handler, pCookie, &hCallback); -} - -void XnFileDevice::UnregisterFromEndOfFileReached(XnCallbackHandle hCallback) -{ - m_eofEvent.Unregister(hCallback); -} - -XnStatus XnFileDevice::ReadNext() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnBool bWrap; - nRetVal = ReadTillNextData(&bWrap); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandlePackedObject(XnPackedDataType nObjectType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nObjectType) - { - case XN_PACKED_NEW_STREAM: - nRetVal = ReadNewStream(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STREAM_REMOVED: - nRetVal = ReadStreamRemoved(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_INT_PROPERTY: - nRetVal = ReadIntProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_REAL_PROPERTY: - nRetVal = ReadRealProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STRING_PROPERTY: - nRetVal = ReadStringProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_GENERAL_PROPERTY: - nRetVal = ReadGeneralProperty(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_STREAM_DATA: - nRetVal = ReadStreamData(); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_PACKED_END: - nRetVal = HandleEndOfStream(); - XN_IS_STATUS_OK(nRetVal); - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Unexpected packed type: %d", nObjectType); - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadNewStream() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - - // create property set - XnPropertySet* pPropertySet = NULL; - nRetVal = XnPropertySetCreate(&pPropertySet); - XN_IS_STATUS_OK(nRetVal); - - // read from stream - nRetVal = m_pDataPacker->ReadNewStream(strType, strName, pPropertySet); - - if (nRetVal == XN_STATUS_OK) - { - // create it - nRetVal = HandleNewStream(strType, strName, pPropertySet->pData->begin().Value()); - } - - XnPropertySetDestroy(&pPropertySet); - - return (nRetVal); -} - -XnProductionNodeType GetNodeType(const XnChar* strType) -{ - if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) - { - return XN_NODE_TYPE_DEPTH; - } - else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) - { - return XN_NODE_TYPE_IMAGE; - } - else if (strcmp(strType, XN_STREAM_TYPE_IR) == 0) - { - return XN_NODE_TYPE_IR; - } - else if (strcmp(strType, XN_STREAM_TYPE_AUDIO) == 0) - { - return XN_NODE_TYPE_AUDIO; - } - else - { - XN_ASSERT(FALSE); - return (XnProductionNodeType)-1; - } -} - -XnStatus XnFileDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if we need to ignore that (stream was not removed upon Rewind). - XnNodeInfoMap::Iterator it = m_ignoreNewNodes.end(); - if (m_ignoreNewNodes.Find(strName, it) == XN_STATUS_OK) - { - // ignore - return (XN_STATUS_OK); - } - - XnProductionNodeType type = GetNodeType(strType); - if (type == -1) - { - XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid node type: %s", strType); - } - - // find compression type - XnActualIntProperty* pComp; - nRetVal = pInitialValues->Get(XN_STREAM_PROPERTY_COMPRESSION, (XnProperty*&)pComp); - XN_IS_STATUS_OK(nRetVal); - - XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)pComp->GetValue()); - if (codecID == XN_CODEC_NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", pComp->GetValue()); - } - - // notify we have a new node - nRetVal = m_pNotifications->OnNodeAdded(m_pNotificationsCookie, strName, type, codecID); - XN_IS_STATUS_OK(nRetVal); - - // we support the mirror capability - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_MIRROR, 1); - XN_IS_STATUS_OK(nRetVal); - - // we support the extended serialization capability - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_EXTENDED_SERIALIZATION, 1); - XN_IS_STATUS_OK(nRetVal); - - // now write state - for (XnActualPropertiesHash::ConstIterator it = pInitialValues->begin(); it != pInitialValues->end(); ++it) - { - XnProperty* pProp = it.Value(); - - switch (pProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; - nRetVal = HandleIntProperty(strName, pProp->GetName(), pIntProp->GetValue()); - } - break; - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; - nRetVal = HandleRealProperty(strName, pProp->GetName(), pRealProp->GetValue()); - } - break; - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; - nRetVal = HandleStringProperty(strName, pProp->GetName(), pStrProp->GetValue()); - } - break; - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; - nRetVal = HandleGeneralProperty(strName, pProp->GetName(), pGenProp->GetValue()); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_FILE, "Unknown property type: %d", pProp->GetType()); - } - - XN_IS_STATUS_OK(nRetVal); - } - - // at this stage, a node should exist with this name - xn::ProductionNode node; - nRetVal = m_context.GetProductionNodeByName(strName, node); - XN_IS_STATUS_OK(nRetVal); - - // S2D & RW - if (type == XN_NODE_TYPE_DEPTH) - { - nRetVal = UpdateS2DTables(xn::DepthGenerator(node)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = UpdateRWData(xn::DepthGenerator(node)); - XN_IS_STATUS_OK(nRetVal); - } - - // notify end-of-state - nRetVal = m_pNotifications->OnNodeStateReady(m_pNotificationsCookie, strName); - XN_IS_STATUS_OK(nRetVal); - - // add it to the map - XnNodeInfo nodeInfo = {0}; - nRetVal = m_nodeInfoMap.Set(strName, nodeInfo); - XN_IS_STATUS_OK(nRetVal); - - // create codec - nRetVal = CreateCodec(node); - XN_IS_STATUS_OK(nRetVal); - - // check IR compatibility - nRetVal = CheckIRCompatibility(node); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::CreateCodec(xn::ProductionNode& node) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnNodeInfo* pNodeInfo = NULL; - if (m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) - { - XnUInt64 nValue; - nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_COMPRESSION, nValue); - XN_IS_STATUS_OK(nRetVal); - - // create new one - XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)nValue); - if (codecID == XN_CODEC_NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", nValue); - } - - if (pNodeInfo->pXnCodec == NULL || pNodeInfo->pXnCodec->GetCompressionFormat() != nValue) - { - // release old codec - XN_DELETE(pNodeInfo->pXnCodec); - pNodeInfo->codec.Unref(); - - // special case: IR recorded with JPEG. This mode is no longer allowed by OpenNI (JPEG - // can now only be used for image). We'll have to handle it ourselves. - if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && - codecID == XN_CODEC_JPEG) - { - xn::IRGenerator irGen(node); - XnMapOutputMode outputMode; - nRetVal = irGen.GetMapOutputMode(outputMode); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW_AND_INIT(pNodeInfo->pXnCodec, XnJpegCodec, TRUE, outputMode.nXRes, outputMode.nYRes); - } - else - { - // normal case - nRetVal = m_context.CreateCodec(codecID, node, pNodeInfo->codec); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW(pNodeInfo->pXnCodec, XnNiCodec, pNodeInfo->codec); - } - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::CheckIRCompatibility(xn::ProductionNode& node) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnNodeInfo* pNodeInfo = NULL; - if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && - m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) - { - XnUInt64 nValue; - nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, nValue); - XN_IS_STATUS_OK(nRetVal); - - pNodeInfo->bIRisRGB = (nValue == XN_OUTPUT_FORMAT_RGB24); - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadStreamRemoved() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read stream name - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - - nRetVal = m_pDataPacker->ReadStreamRemoved(strName); - XN_IS_STATUS_OK(nRetVal); - - // remove it - nRetVal = HandleStreamRemoved(strName); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleStreamRemoved(const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check for specific case: all streams are removed and then end-of-file is reached. - // in this case, we don't really want to destroy streams, just wrap around. - XnStringsHash StreamsToRemove; - nRetVal = StreamsToRemove.Set(strName, NULL); - XN_IS_STATUS_OK(nRetVal); - - XnPackedDataType nType = XN_PACKED_STREAM_REMOVED; - XnUInt32 nPositionBefore; - - while (TRUE) - { - nRetVal = m_pInputStream->Tell(&nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pDataPacker->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_STREAM_REMOVED) - { - XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = m_pDataPacker->ReadStreamRemoved(strTempName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = StreamsToRemove.Set(strTempName, NULL); - XN_IS_STATUS_OK(nRetVal); - } - else - { - break; - } - } - - if (nType != XN_PACKED_END) - { - // Not the case we were looking for. Remove those streams. - for (XnStringsHash::Iterator it = StreamsToRemove.begin(); it != StreamsToRemove.end(); ++it) - { - nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, it.Key()); - XN_IS_STATUS_OK(nRetVal); - - XnNodeInfo* pNodeInfo; - m_nodeInfoMap.Get(it.Key(), pNodeInfo); - XN_DELETE(pNodeInfo->pXnCodec); - m_nodeInfoMap.Remove(it.Key()); - m_ignoreNewNodes.Remove(it.Key()); - } - - m_bNodeCollectionChanged = TRUE; - } - - // in any case, the last object we read wasn't handled yet (end-of-stream or another event), so - // seek back, so it will be handled. - nRetVal = m_pInputStream->Seek(nPositionBefore); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadIntProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt64 nValue; - - // read change data - nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleIntProperty(strModule, strProp, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleIntProperty(const XnChar *strModule, const XnChar *strName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // ignore some properties - if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) - { - return (XN_STATUS_OK); - } - - // OpenNI props - if (strcmp(strName, XN_STREAM_PROPERTY_STATE) == 0) - { - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_IS_GENERATING, nValue); - } - else if (strcmp(strName, XN_MODULE_PROPERTY_MIRROR) == 0) - { - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MIRROR, nValue); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) - { - xn::MapGenerator node; - nRetVal = m_context.GetProductionNodeByName(strModule, node); - XN_IS_STATUS_OK(nRetVal); - - XnMapOutputMode mode; - nRetVal = node.GetMapOutputMode(mode); - XN_IS_STATUS_OK(nRetVal); - - if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) - { - mode.nXRes = nValue; - } - else if (strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0) - { - mode.nYRes = nValue; - } - else if (strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) - { - mode.nFPS = nValue; - } - - // change supported modes to this one - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES_COUNT, 1); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES, sizeof(XnMapOutputMode), &mode); - XN_IS_STATUS_OK(nRetVal); - - // and set actual mode - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MAP_OUTPUT_MODE, sizeof(mode), &mode); - XN_IS_STATUS_OK(nRetVal); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) - { - switch (nValue) - { - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - case XN_OUTPUT_FORMAT_GRAYSCALE16: - case XN_OUTPUT_FORMAT_PCM: - break; - case XN_OUTPUT_FORMAT_GRAYSCALE8: - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_GRAYSCALE_8_BIT); - break; - case XN_OUTPUT_FORMAT_RGB24: - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_RGB24); - break; - case XN_OUTPUT_FORMAT_YUV422: - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_YUV422); - break; - default: - XN_ASSERT(FALSE); - return XN_STATUS_ERROR; - } - - XN_IS_STATUS_OK(nRetVal); - - // also set property (we need it for IR compatibility) - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0) - { - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_DEVICE_MAX_DEPTH, nValue); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) - { - xn::AudioGenerator node; - nRetVal = m_context.GetProductionNodeByName(strModule, node); - XN_IS_STATUS_OK(nRetVal); - - XnWaveOutputMode mode; - nRetVal = node.GetWaveOutputMode(mode); - XN_IS_STATUS_OK(nRetVal); - - if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0) - { - mode.nSampleRate = nValue; - } - else if (strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) - { - mode.nChannels = nValue; - } - - // change supported modes to this one - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES_COUNT, 1); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES, sizeof(XnWaveOutputMode), &mode); - XN_IS_STATUS_OK(nRetVal); - - // and set actual mode - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_OUTPUT_MODE, sizeof(mode), &mode); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); - } - - XN_IS_STATUS_OK(nRetVal); - - /********************/ - // Now for some additional logic... - /********************/ - - xn::ProductionNode node; - nRetVal = m_context.GetProductionNodeByName(strModule, node); - XN_IS_STATUS_OK(nRetVal); - - // replace codec? - if (strcmp(strName, XN_STREAM_PROPERTY_COMPRESSION) == 0) - { - nRetVal = CreateCodec(node); - XN_IS_STATUS_OK(nRetVal); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) - { - nRetVal = CheckIRCompatibility(node); - XN_IS_STATUS_OK(nRetVal); - } - else if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && - strcmp(strName, XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS) == 0) - { - // check timestamps resolution - m_bHighresTimestamps = (nValue == TRUE); - } - else if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_MAX_SHIFT) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_CONST_SHIFT) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_PARAM_COEFF) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_SHIFT_SCALE) == 0) - { - // only after node is ready - xn::DepthGenerator depth(node); - XnNodeInfo* pNodeInfo; - if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && - m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) - { - nRetVal = UpdateS2DTables(depth); - XN_IS_STATUS_OK(nRetVal); - } - } - - if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) - { - // only after node is ready - XnNodeInfo* pNodeInfo; - if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK) - { - // check this is a depth node - if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_DEPTH) - { - xn::DepthGenerator depth(node); - nRetVal = UpdateRWData(depth); - XN_IS_STATUS_OK(nRetVal); - } - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadRealProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnDouble dValue; - - // read change data - nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &dValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleRealProperty(strModule, strProp, dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleRealProperty(const XnChar *strModule, const XnChar *strName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pNotifications->OnNodeRealPropChanged(m_pNotificationsCookie, strModule, strName, dValue); - XN_IS_STATUS_OK(nRetVal); - - XnNodeInfo* pNodeInfo; - - if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0 || - strcmp(strName, XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE) == 0) - { - // only after node is ready - xn::DepthGenerator depth; - if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && - m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) - { - nRetVal = UpdateS2DTables(depth); - XN_IS_STATUS_OK(nRetVal); - } - } - - if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0) - { - // only after node is ready - xn::DepthGenerator depth; - if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && - m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) - { - nRetVal = UpdateRWData(depth); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadStringProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - - // read change data - nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleStringProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleStringProperty(const XnChar *strModule, const XnChar *strName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pNotifications->OnNodeStringPropChanged(m_pNotificationsCookie, strModule, strName, strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadGeneralProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnGeneralBuffer gbValue; - - // read change data - nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &gbValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleGeneralProperty(strModule, strProp, gbValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // OpenNI props - if (strcmp(strName, XN_STREAM_PROPERTY_CROPPING) == 0) - { - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_CROPPING, sizeof(XnCropping), gbValue.pData); - } - else - { - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, strName, gbValue.nDataSize, gbValue.pData); - } - - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadStreamData() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnCompressionFormats nCompression; - XnUInt32 nCompressedSize; - nRetVal = m_pDataPacker->ReadStreamDataProps(m_pStreamData, &nCompression, &nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandleStreamData(m_pStreamData, nCompression, nCompressedSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void TransformRGB24ToGrayscale16(XnUInt8* pBuffer, XnUInt32* pnBufferSize) -{ - XnRGB24Pixel* pInput = (XnRGB24Pixel*)pBuffer; - XnRGB24Pixel* pBufferEnd = (XnRGB24Pixel*)(pBuffer + *pnBufferSize); - XnUInt16* pOutput = (XnUInt16*)pBuffer; - - while (pInput < pBufferEnd) - { - *pOutput = ((XnUInt16)pInput->nRed) << 2; - pInput++; - pOutput++; - } - - *pnBufferSize = (XnUInt8*)pOutput - pBuffer; -} - -XnStatus XnFileDevice::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nPosition; - nRetVal = m_pInputStream->Tell(&nPosition); - XN_IS_STATUS_OK(nRetVal); - - XnUIntHash::Iterator it = m_PositionsToIgnore.end(); - if (XN_STATUS_OK == m_PositionsToIgnore.Find(nPosition, it)) - { - // ignore this one. Just update the frame ID - XnNodeInfo* pNodeInfo; - nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - pNodeInfo->nCurrFrameID++; - - // and remove it from list - nRetVal = m_PositionsToIgnore.Remove(it); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // take the codec - XnNodeInfo* pNodeInfo; - nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); - XN_IS_STATUS_OK(nRetVal); - - // now uncompress data - nRetVal = m_pDataPacker->ReadStreamData(pDataProps, pNodeInfo->pXnCodec); - XN_IS_STATUS_OK(nRetVal); - - if (!m_bHighresTimestamps) - { - pDataProps->nTimestamp *= 1000; - } - - if (pNodeInfo->bIRisRGB) - { - // covert RGB IR to regular IR - TransformRGB24ToGrayscale16((XnUInt8*)pDataProps->pData, &pDataProps->nDataSize); - } - - // update curr timestamp - if (pDataProps->nTimestamp > m_nCurrTimestamp) - { - m_nCurrTimestamp = pDataProps->nTimestamp; - } - - // update frame ID - ++pNodeInfo->nCurrFrameID; - - // and notify about new data - nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, pDataProps->StreamName, pDataProps->nTimestamp, pNodeInfo->nCurrFrameID, pDataProps->pData, pDataProps->nDataSize); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::HandleEndOfStream() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bFileHasData) - { - XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "File does not contain any data..."); - } - - nRetVal = m_eofEvent.Raise(); - XN_IS_STATUS_OK(nRetVal); - - if (m_bRepeat) - { - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - } - else - { - m_bEOF = TRUE; - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadNextEventFromStream(XnPackedDataType* pnObjectType /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnPackedDataType nObjectType; - - nRetVal = m_pDataPacker->ReadNextObject(&nObjectType); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = HandlePackedObject(nObjectType); - XN_IS_STATUS_OK(nRetVal); - - if (pnObjectType != NULL) - { - *pnObjectType = nObjectType; - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::ReadTillNextData(XnBool* pbWrapOccurred) -{ - XnStatus nRetVal = XN_STATUS_OK; - - *pbWrapOccurred = FALSE; - - if (m_nFileVersion < 4) - { - nRetVal = BCReadFrame(pbWrapOccurred); - XN_IS_STATUS_OK(nRetVal); - } - else - { - XnPackedDataType nType = XN_PACKED_END; - while ((nType != XN_PACKED_STREAM_DATA) && (!m_bEOF)) - { - nRetVal = ReadNextEventFromStream(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_PACKED_END) - { - *pbWrapOccurred = TRUE; - } - } - - if (nType == XN_PACKED_STREAM_DATA) - { - m_bFileHasData = TRUE; - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::Rewind() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // go back to start of stream - nRetVal = m_pInputStream->Seek(XN_DEVICE_FILE_MAGIC_LEN); - XN_IS_STATUS_OK(nRetVal); - - // read initial state - XN_PROPERTY_SET_CREATE_ON_STACK(state); - nRetVal = ReadInitialState(&state); - XN_IS_STATUS_OK(nRetVal); - - // first handle current streams. remove or reset them - for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) - { - const XnChar* strName = it.Key(); - - if (m_bNodeCollectionChanged) - { - // we need to destroy all streams, and recreate them later - nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, strName); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // just reset frame ID - it.Value().nCurrFrameID = 0; - // and mark not to recreate it - nRetVal = m_ignoreNewNodes.Set(strName, it.Value()); - XN_IS_STATUS_OK(nRetVal); - } - } - - // if we need, recreate nodes - if (m_bNodeCollectionChanged) - { - nRetVal = SetInitialState(&state); - XN_IS_STATUS_OK(nRetVal); - } - -// ResetLastTimestampAndFrame(); -// m_nReferenceTimestamp = 0; -// m_nReferenceTime = 0; - - m_bNodeCollectionChanged = FALSE; - m_nCurrTimestamp = 0; - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::UpdateS2DTables(const xn::DepthGenerator& depth) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nTemp; - XnDouble dTemp; - - // get config - XnShiftToDepthConfig config; - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nZeroPlaneDistance = nTemp; - - nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, dTemp); - XN_IS_STATUS_OK(nRetVal); - config.fZeroPlanePixelSize = dTemp; - - nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, dTemp); - XN_IS_STATUS_OK(nRetVal); - config.fEmitterDCmosDistance = dTemp; - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_MAX_SHIFT, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nDeviceMaxShiftValue = nTemp; - - config.nDeviceMaxDepthValue = depth.GetDeviceMaxDepth(); - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_CONST_SHIFT, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nConstShift = nTemp; - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nPixelSizeFactor = nTemp; - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PARAM_COEFF, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nParamCoeff = nTemp; - - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, nTemp); - XN_IS_STATUS_OK(nRetVal); - config.nShiftScale = nTemp; - - config.nDepthMinCutOff = 0; - config.nDepthMaxCutOff = config.nDeviceMaxDepthValue; - - if (!m_ShiftToDepth.bIsInitialized) - { - nRetVal = XnShiftToDepthInit(&m_ShiftToDepth, &config); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nRetVal = XnShiftToDepthUpdate(&m_ShiftToDepth, &config); - XN_IS_STATUS_OK(nRetVal); - } - - // notify - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_S2D_TABLE, m_ShiftToDepth.nShiftsCount * sizeof(XnDepthPixel), m_ShiftToDepth.pShiftToDepthTable); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_D2S_TABLE, m_ShiftToDepth.nDepthsCount * sizeof(XnUInt16), m_ShiftToDepth.pDepthToShiftTable); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::UpdateRWData(const xn::DepthGenerator& depth) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nZPD; - nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nZPD); - XN_IS_STATUS_OK(nRetVal); - - XnDouble fZPPS; - nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, fZPPS); - XN_IS_STATUS_OK(nRetVal); - - XnFieldOfView FOV; - FOV.fHFOV = 2*atan(fZPPS*XN_SXGA_X_RES/2/nZPD); - FOV.fVFOV = 2*atan(fZPPS*XN_VGA_Y_RES*2/2/nZPD); - - // notify - nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, - depth.GetName(), - XN_PROP_FIELD_OF_VIEW, - sizeof(FOV), - &FOV); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFileDevice.h" +#include +#include +#include +#include "XnDeviceFileReaderBC.h" +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE (1600 * 1200 * sizeof(XnRGB24Pixel)) + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnLastStreamData +{ + XnUInt32 nPosition; + XnUInt32 nFrameID; + XnUInt64 nTimestamp; +} XnLastStreamData; + +XN_DECLARE_STRINGS_HASH(XnLastStreamData, XnLastStreamDataHash); + +//--------------------------------------------------------------------------- +// XnFileDevice class +//--------------------------------------------------------------------------- +XnFileDevice::XnFileDevice(xn::Context& context, const XnChar* strInstanceName) : + m_context(context), + m_pInputStream(NULL), + m_pDataPacker(NULL), + m_pNotifications(NULL), + m_pNotificationsCookie(NULL), + m_bHighresTimestamps(FALSE), + m_pStreamData(NULL), + m_bFileHasData(FALSE), + m_bNodeCollectionChanged(FALSE), + m_nCurrTimestamp(0), + m_pBCData(NULL), + m_bRepeat(TRUE), + m_bEOF(FALSE) +{ + xnOSMemSet(&m_ShiftToDepth, 0, sizeof(m_ShiftToDepth)); +} + +XnFileDevice::~XnFileDevice() +{ + Free(); +} + +XnStatus XnFileDevice::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamDataCreate(&m_pStreamData, "", XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnFileDevice::Free() +{ + for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) + { + XnNodeInfo& nodeInfo = it.Value(); + XN_DELETE(nodeInfo.pXnCodec); + } + m_nodeInfoMap.Clear(); + + if (m_ShiftToDepth.bIsInitialized) + { + XnShiftToDepthFree(&m_ShiftToDepth); + } + + if (m_pInputStream != NULL) + { + XN_DELETE(m_pInputStream); + m_pInputStream = NULL; + } + + if (m_pDataPacker != NULL) + { + m_pDataPacker->Free(); + XN_DELETE(m_pDataPacker); + m_pDataPacker = NULL; + } + + if (m_pStreamData != NULL) + { + XnStreamDataDestroy(&m_pStreamData); + m_pStreamData = NULL; + } +} + +XnStatus XnFileDevice::ReadFileVersion() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read magic from file + XnChar csFileMagic[XN_DEVICE_FILE_MAGIC_LEN]; + nRetVal = m_pInputStream->ReadData((XnUChar*)csFileMagic, XN_DEVICE_FILE_MAGIC_LEN); + XN_IS_STATUS_OK(nRetVal); + + if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V4, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 4; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V3, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 3; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V2, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 2; + } + else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V1, XN_DEVICE_FILE_MAGIC_LEN) == 0) + { + m_nFileVersion = 1; + } + else + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "Invalid file magic!"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadInitialState(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_nFileVersion < 4) + { + if (m_pBCData == NULL) + { + nRetVal = BCInit(); + XN_IS_STATUS_OK(nRetVal); + } + + return BCReadInitialState(pSet); + } + + // read an object from data packer + XnPackedDataType nType; + nRetVal = m_pDataPacker->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType != XN_PACKED_PROPERTY_SET) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Stream does not start with a property set!"); + } + + nRetVal = m_pDataPacker->ReadPropertySet(pSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SetInitialState(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Fix state (remove some properties that we don't wish to reflect in reader device) + XnActualPropertiesHash* pDeviceModule = NULL; + if (XN_STATUS_OK == pSet->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModule)) + { + pDeviceModule->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); + pDeviceModule->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); + + // check for timestamps resolution + XnActualIntProperty* pIntProp; + if (XN_STATUS_OK == pDeviceModule->Get(XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, (XnProperty*&)pIntProp)) + { + m_bHighresTimestamps = (pIntProp->GetValue() == TRUE); + } + } + + // TODO: create DEVICE node + + // now create the rest of the modules and streams (DEVICE was already created) + XnPropertySetData* pPropSetData = pSet->pData; + for (XnPropertySetData::ConstIterator it = pPropSetData->begin(); it != pPropSetData->end(); ++it) + { + // ignore module DEVICE + if (strcmp(XN_MODULE_NAME_DEVICE, it.Key()) == 0) + { + continue; + } + + // check if this is a stream + XnActualPropertiesHash::ConstIterator itProp = it.Value()->end(); + if (XN_STATUS_OK == it.Value()->Find(XN_STREAM_PROPERTY_TYPE, itProp)) + { + XnActualStringProperty* pTypeProp = (XnActualStringProperty*)itProp.Value(); + nRetVal = HandleNewStream(pTypeProp->GetValue(), it.Key(), it.Value()); + XN_IS_STATUS_OK(nRetVal); + } + } // modules loop + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SetInputStream(void *pStreamCookie, XnPlayerInputStreamInterface *pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_NEW(m_pInputStream, XnInputStream, pStream, pStreamCookie); + + nRetVal = m_pInputStream->Init(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(m_pInputStream); + return (nRetVal); + } + + // read format version + nRetVal = ReadFileVersion(); + XN_IS_STATUS_OK(nRetVal); + + m_pDataPacker = XN_NEW(XnDataPacker, m_pInputStream, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER); + if (m_pDataPacker == NULL) + { + XN_DELETE(m_pInputStream); + return (XN_STATUS_ALLOC_FAILED); + } + + nRetVal = m_pDataPacker->Init(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(m_pDataPacker); + XN_DELETE(m_pInputStream); + return (nRetVal); + } + + // read initial state + XN_PROPERTY_SET_CREATE_ON_STACK(props); + nRetVal = ReadInitialState(&props); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetInitialState(&props); + XN_IS_STATUS_OK(nRetVal); + + // now read till first data + XnBool bWrap; + nRetVal = ReadTillNextData(&bWrap); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SetNodeNotifications(void *pNodeNotificationsCookie, XnNodeNotifications *pNodeNotifications) +{ + m_pNotifications = pNodeNotifications; + m_pNotificationsCookie = pNodeNotificationsCookie; + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SetRepeat(XnBool bRepeat) +{ + m_bRepeat = bRepeat; + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SeekTo(XnUInt64 nMinTimestamp, const XnChar* strNodeName, XnUInt32 nMinFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first check if we need to seek forward or backwards (even if we're in the correct location, + // we need to rewind, so that next read will return this frame again). + XnNodeInfo* pNodeInfo = NULL; + if (strNodeName != NULL) + { + nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + if (nMinFrameID <= pNodeInfo->nCurrFrameID) + { + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + } + } + else + { + if (nMinTimestamp <= m_nCurrTimestamp) + { + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + } + } + + XnBool bFoundNewData = FALSE; + + // Keep current position. + XnUInt32 nStartingPosition; + nRetVal = m_pInputStream->Tell(&nStartingPosition); + XN_IS_STATUS_OK(nRetVal); + + // start seeking forward until point is reached. + XnUInt32 nFoundPosition; + XnPackedDataType nType = (XnPackedDataType)-1; + XnLastStreamDataHash StreamsHash; + + while (TRUE) + { + XnUInt32 nPositionBefore; + nRetVal = m_pInputStream->Tell(&nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pDataPacker->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + XnUInt32 nPositionAfter; + nRetVal = m_pInputStream->Tell(&nPositionAfter); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_STREAM_DATA) + { + bFoundNewData = TRUE; + + XnStreamData props; + XnCompressionFormats nCompression; + XnUInt32 nCompressedSize; + nRetVal = m_pDataPacker->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + XnLastStreamData data; + if (XN_STATUS_OK != StreamsHash.Get(props.StreamName, data)) + { + XnNodeInfo* pNodeInfo; + nRetVal = m_nodeInfoMap.Get(props.StreamName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + data.nFrameID = pNodeInfo->nCurrFrameID + 1; + } + else + { + // if we had previous data from this stream, ignore it + m_PositionsToIgnore.Set(data.nPosition, 0); + + ++data.nFrameID; + } + + data.nPosition = nPositionAfter; + data.nTimestamp = props.nTimestamp; + nRetVal = StreamsHash.Set(props.StreamName, data); + XN_IS_STATUS_OK(nRetVal); + + // now check if condition is met + if (strNodeName != NULL) + { + if (strcmp(strNodeName, props.StreamName) == 0 && + data.nFrameID >= nMinFrameID) + { + // keep this position (we'll read up till here). + nFoundPosition = nPositionAfter; + break; + } + } + else if (data.nTimestamp >= nMinTimestamp) + { + // keep this position (we'll read up till here). + nFoundPosition = nPositionAfter; + break; + } + } + else if (nType == XN_PACKED_END) + { + // we'll read up to the last data of each stream + nFoundPosition = nPositionBefore; + break; + } + } + + // now seek back + nRetVal = m_pInputStream->Seek(nStartingPosition); + XN_IS_STATUS_OK(nRetVal); + + if (bFoundNewData) + { + // read everything up to position + XnUInt32 nPositionAfter = nStartingPosition; + + while (nPositionAfter < nFoundPosition) + { + nRetVal = ReadNextEventFromStream(&nType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pInputStream->Tell(&nPositionAfter); + XN_IS_STATUS_OK(nRetVal); + } + } + else + { +/* // just remark the data as new (this is last frame, return it again to user) + XnDeviceModuleHolderList streams; + nRetVal = GetStreamsList(streams); + XN_IS_STATUS_OK(nRetVal); + + for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) + { + XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); + pStream->ReMarkDataAsNew(); + } +*/ } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::SeekToTimeStamp(XnInt64 nTimeOffset, XnPlayerSeekOrigin origin) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nTimestamp = 0; + if (origin == XN_PLAYER_SEEK_CUR) + { + nTimestamp = m_nCurrTimestamp + nTimeOffset; + } + else if (origin == XN_PLAYER_SEEK_SET) + { + nTimestamp = nTimeOffset; + } + else + { + // TODO: find max timestamp and add offset + return XN_STATUS_NOT_IMPLEMENTED; + } + + xnLogInfo(XN_MASK_FILE, "Seeking file to timestamp %llu...", nTimestamp); + + if (m_nFileVersion < 4) + { + return BCSeek(nTimestamp); + } + else + { + return SeekTo(nTimestamp, NULL, 0); + } +} + +XnStatus XnFileDevice::SeekToFrame(const XnChar* strNodeName, XnInt32 nFrameOffset, XnPlayerSeekOrigin origin) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnNodeInfo* pNodeInfo; + nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + XnInt32 nFrameID = 0; + + switch (origin) + { + case XN_PLAYER_SEEK_CUR: + nFrameID = pNodeInfo->nCurrFrameID + nFrameOffset; + break; + case XN_PLAYER_SEEK_SET: + nFrameID = nFrameOffset; + break; + case XN_PLAYER_SEEK_END: + // TODO: handle + return XN_STATUS_NOT_IMPLEMENTED; + } + + // don't allow seeking to frame 0 + nFrameID = XN_MAX(nFrameID, 1); + + xnLogInfo(XN_MASK_FILE, "Seeking file to frameID %u of node %s...", nFrameID, strNodeName); + + if (m_nFileVersion < 4) + { + return BCSeekFrame(nFrameID); + } + else + { + nRetVal = SeekTo(0, strNodeName, nFrameID); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::TellTimestamp(XnUInt64& nTimestamp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nTimestamp = m_nCurrTimestamp; + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::TellFrame(const XnChar* strNodeName, XnUInt32 &nFrameOffset) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnNodeInfo* pNodeInfo; + nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + nFrameOffset = pNodeInfo->nCurrFrameID; + + return (XN_STATUS_OK); +} + + +XnStatus XnFileDevice::GetNumFrames(const XnChar* strNodeName, XnUInt32& nFrames) +{ + XnStatus nRetVal = XN_STATUS_OK; + xn::ProductionNode node; + nRetVal = m_context.GetProductionNodeByName(strNodeName, node); + XN_IS_STATUS_OK(nRetVal); + XnUInt64 nFrames64 = 0; + nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, nFrames64); + XN_IS_STATUS_OK(nRetVal); + nFrames = (XnUInt32)nFrames64; + + return XN_STATUS_OK; +} + +XnBool XnFileDevice::IsEOF() +{ + return m_bEOF; +} + +XnStatus XnFileDevice::RegisterToEndOfFileReached(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + return m_eofEvent.Register(handler, pCookie, &hCallback); +} + +void XnFileDevice::UnregisterFromEndOfFileReached(XnCallbackHandle hCallback) +{ + m_eofEvent.Unregister(hCallback); +} + +XnStatus XnFileDevice::ReadNext() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnBool bWrap; + nRetVal = ReadTillNextData(&bWrap); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandlePackedObject(XnPackedDataType nObjectType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nObjectType) + { + case XN_PACKED_NEW_STREAM: + nRetVal = ReadNewStream(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STREAM_REMOVED: + nRetVal = ReadStreamRemoved(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_INT_PROPERTY: + nRetVal = ReadIntProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_REAL_PROPERTY: + nRetVal = ReadRealProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STRING_PROPERTY: + nRetVal = ReadStringProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_GENERAL_PROPERTY: + nRetVal = ReadGeneralProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_STREAM_DATA: + nRetVal = ReadStreamData(); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_PACKED_END: + nRetVal = HandleEndOfStream(); + XN_IS_STATUS_OK(nRetVal); + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Unexpected packed type: %d", nObjectType); + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadNewStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + + // create property set + XnPropertySet* pPropertySet = NULL; + nRetVal = XnPropertySetCreate(&pPropertySet); + XN_IS_STATUS_OK(nRetVal); + + // read from stream + nRetVal = m_pDataPacker->ReadNewStream(strType, strName, pPropertySet); + + if (nRetVal == XN_STATUS_OK) + { + // create it + nRetVal = HandleNewStream(strType, strName, pPropertySet->pData->begin().Value()); + } + + XnPropertySetDestroy(&pPropertySet); + + return (nRetVal); +} + +XnProductionNodeType GetNodeType(const XnChar* strType) +{ + if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) + { + return XN_NODE_TYPE_DEPTH; + } + else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) + { + return XN_NODE_TYPE_IMAGE; + } + else if (strcmp(strType, XN_STREAM_TYPE_IR) == 0) + { + return XN_NODE_TYPE_IR; + } + else if (strcmp(strType, XN_STREAM_TYPE_AUDIO) == 0) + { + return XN_NODE_TYPE_AUDIO; + } + else + { + XN_ASSERT(FALSE); + return (XnProductionNodeType)-1; + } +} + +XnStatus XnFileDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if we need to ignore that (stream was not removed upon Rewind). + XnNodeInfoMap::Iterator it = m_ignoreNewNodes.end(); + if (m_ignoreNewNodes.Find(strName, it) == XN_STATUS_OK) + { + // ignore + return (XN_STATUS_OK); + } + + XnProductionNodeType type = GetNodeType(strType); + if (type == -1) + { + XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid node type: %s", strType); + } + + // find compression type + XnActualIntProperty* pComp; + nRetVal = pInitialValues->Get(XN_STREAM_PROPERTY_COMPRESSION, (XnProperty*&)pComp); + XN_IS_STATUS_OK(nRetVal); + + XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)pComp->GetValue()); + if (codecID == XN_CODEC_NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", pComp->GetValue()); + } + + // notify we have a new node + nRetVal = m_pNotifications->OnNodeAdded(m_pNotificationsCookie, strName, type, codecID); + XN_IS_STATUS_OK(nRetVal); + + // we support the mirror capability + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_MIRROR, 1); + XN_IS_STATUS_OK(nRetVal); + + // we support the extended serialization capability + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_EXTENDED_SERIALIZATION, 1); + XN_IS_STATUS_OK(nRetVal); + + // now write state + for (XnActualPropertiesHash::ConstIterator it = pInitialValues->begin(); it != pInitialValues->end(); ++it) + { + XnProperty* pProp = it.Value(); + + switch (pProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; + nRetVal = HandleIntProperty(strName, pProp->GetName(), pIntProp->GetValue()); + } + break; + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; + nRetVal = HandleRealProperty(strName, pProp->GetName(), pRealProp->GetValue()); + } + break; + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; + nRetVal = HandleStringProperty(strName, pProp->GetName(), pStrProp->GetValue()); + } + break; + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; + nRetVal = HandleGeneralProperty(strName, pProp->GetName(), pGenProp->GetValue()); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_FILE, "Unknown property type: %d", pProp->GetType()); + } + + XN_IS_STATUS_OK(nRetVal); + } + + // at this stage, a node should exist with this name + xn::ProductionNode node; + nRetVal = m_context.GetProductionNodeByName(strName, node); + XN_IS_STATUS_OK(nRetVal); + + // S2D & RW + if (type == XN_NODE_TYPE_DEPTH) + { + nRetVal = UpdateS2DTables(xn::DepthGenerator(node)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = UpdateRWData(xn::DepthGenerator(node)); + XN_IS_STATUS_OK(nRetVal); + } + + // notify end-of-state + nRetVal = m_pNotifications->OnNodeStateReady(m_pNotificationsCookie, strName); + XN_IS_STATUS_OK(nRetVal); + + // add it to the map + XnNodeInfo nodeInfo = {0}; + nRetVal = m_nodeInfoMap.Set(strName, nodeInfo); + XN_IS_STATUS_OK(nRetVal); + + // create codec + nRetVal = CreateCodec(node); + XN_IS_STATUS_OK(nRetVal); + + // check IR compatibility + nRetVal = CheckIRCompatibility(node); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::CreateCodec(xn::ProductionNode& node) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnNodeInfo* pNodeInfo = NULL; + if (m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) + { + XnUInt64 nValue; + nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_COMPRESSION, nValue); + XN_IS_STATUS_OK(nRetVal); + + // create new one + XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)nValue); + if (codecID == XN_CODEC_NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", nValue); + } + + if (pNodeInfo->pXnCodec == NULL || pNodeInfo->pXnCodec->GetCompressionFormat() != nValue) + { + // release old codec + XN_DELETE(pNodeInfo->pXnCodec); + pNodeInfo->codec.Release(); + + // special case: IR recorded with JPEG. This mode is no longer allowed by OpenNI (JPEG + // can now only be used for image). We'll have to handle it ourselves. + if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && + codecID == XN_CODEC_JPEG) + { + xn::IRGenerator irGen(node); + XnMapOutputMode outputMode; + nRetVal = irGen.GetMapOutputMode(outputMode); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_NEW_AND_INIT(pNodeInfo->pXnCodec, XnJpegCodec, TRUE, outputMode.nXRes, outputMode.nYRes); + } + else + { + // normal case + nRetVal = m_context.CreateCodec(codecID, node, pNodeInfo->codec); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_NEW(pNodeInfo->pXnCodec, XnNiCodec, pNodeInfo->codec); + } + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::CheckIRCompatibility(xn::ProductionNode& node) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnNodeInfo* pNodeInfo = NULL; + if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && + m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) + { + XnUInt64 nValue; + nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, nValue); + XN_IS_STATUS_OK(nRetVal); + + pNodeInfo->bIRisRGB = (nValue == XN_OUTPUT_FORMAT_RGB24); + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadStreamRemoved() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read stream name + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + + nRetVal = m_pDataPacker->ReadStreamRemoved(strName); + XN_IS_STATUS_OK(nRetVal); + + // remove it + nRetVal = HandleStreamRemoved(strName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleStreamRemoved(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check for specific case: all streams are removed and then end-of-file is reached. + // in this case, we don't really want to destroy streams, just wrap around. + XnStringsHash StreamsToRemove; + nRetVal = StreamsToRemove.Set(strName, NULL); + XN_IS_STATUS_OK(nRetVal); + + XnPackedDataType nType = XN_PACKED_STREAM_REMOVED; + XnUInt32 nPositionBefore; + + while (TRUE) + { + nRetVal = m_pInputStream->Tell(&nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pDataPacker->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_STREAM_REMOVED) + { + XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = m_pDataPacker->ReadStreamRemoved(strTempName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = StreamsToRemove.Set(strTempName, NULL); + XN_IS_STATUS_OK(nRetVal); + } + else + { + break; + } + } + + if (nType != XN_PACKED_END) + { + // Not the case we were looking for. Remove those streams. + for (XnStringsHash::Iterator it = StreamsToRemove.begin(); it != StreamsToRemove.end(); ++it) + { + nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, it.Key()); + XN_IS_STATUS_OK(nRetVal); + + XnNodeInfo* pNodeInfo; + m_nodeInfoMap.Get(it.Key(), pNodeInfo); + XN_DELETE(pNodeInfo->pXnCodec); + m_nodeInfoMap.Remove(it.Key()); + m_ignoreNewNodes.Remove(it.Key()); + } + + m_bNodeCollectionChanged = TRUE; + } + + // in any case, the last object we read wasn't handled yet (end-of-stream or another event), so + // seek back, so it will be handled. + nRetVal = m_pInputStream->Seek(nPositionBefore); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadIntProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt64 nValue; + + // read change data + nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleIntProperty(strModule, strProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleIntProperty(const XnChar *strModule, const XnChar *strName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // ignore some properties + if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) + { + return (XN_STATUS_OK); + } + + // OpenNI props + if (strcmp(strName, XN_STREAM_PROPERTY_STATE) == 0) + { + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_IS_GENERATING, nValue); + } + else if (strcmp(strName, XN_MODULE_PROPERTY_MIRROR) == 0) + { + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MIRROR, nValue); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) + { + xn::MapGenerator node; + nRetVal = m_context.GetProductionNodeByName(strModule, node); + XN_IS_STATUS_OK(nRetVal); + + XnMapOutputMode mode; + nRetVal = node.GetMapOutputMode(mode); + XN_IS_STATUS_OK(nRetVal); + + if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) + { + mode.nXRes = nValue; + } + else if (strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0) + { + mode.nYRes = nValue; + } + else if (strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) + { + mode.nFPS = nValue; + } + + // change supported modes to this one + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES_COUNT, 1); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES, sizeof(XnMapOutputMode), &mode); + XN_IS_STATUS_OK(nRetVal); + + // and set actual mode + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MAP_OUTPUT_MODE, sizeof(mode), &mode); + XN_IS_STATUS_OK(nRetVal); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) + { + switch (nValue) + { + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + case XN_OUTPUT_FORMAT_GRAYSCALE16: + case XN_OUTPUT_FORMAT_PCM: + break; + case XN_OUTPUT_FORMAT_GRAYSCALE8: + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_GRAYSCALE_8_BIT); + break; + case XN_OUTPUT_FORMAT_RGB24: + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_RGB24); + break; + case XN_OUTPUT_FORMAT_YUV422: + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_YUV422); + break; + default: + XN_ASSERT(FALSE); + return XN_STATUS_ERROR; + } + + XN_IS_STATUS_OK(nRetVal); + + // also set property (we need it for IR compatibility) + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0) + { + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_DEVICE_MAX_DEPTH, nValue); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) + { + xn::AudioGenerator node; + nRetVal = m_context.GetProductionNodeByName(strModule, node); + XN_IS_STATUS_OK(nRetVal); + + XnWaveOutputMode mode; + nRetVal = node.GetWaveOutputMode(mode); + XN_IS_STATUS_OK(nRetVal); + + if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0) + { + mode.nSampleRate = nValue; + } + else if (strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) + { + mode.nChannels = nValue; + } + + // change supported modes to this one + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES_COUNT, 1); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES, sizeof(XnWaveOutputMode), &mode); + XN_IS_STATUS_OK(nRetVal); + + // and set actual mode + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_OUTPUT_MODE, sizeof(mode), &mode); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); + } + + XN_IS_STATUS_OK(nRetVal); + + /********************/ + // Now for some additional logic... + /********************/ + + xn::ProductionNode node; + nRetVal = m_context.GetProductionNodeByName(strModule, node); + XN_IS_STATUS_OK(nRetVal); + + // replace codec? + if (strcmp(strName, XN_STREAM_PROPERTY_COMPRESSION) == 0) + { + nRetVal = CreateCodec(node); + XN_IS_STATUS_OK(nRetVal); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) + { + nRetVal = CheckIRCompatibility(node); + XN_IS_STATUS_OK(nRetVal); + } + else if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && + strcmp(strName, XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS) == 0) + { + // check timestamps resolution + m_bHighresTimestamps = (nValue == TRUE); + } + else if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_MAX_SHIFT) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_CONST_SHIFT) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_PARAM_COEFF) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_SHIFT_SCALE) == 0) + { + // only after node is ready + xn::DepthGenerator depth(node); + XnNodeInfo* pNodeInfo; + if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && + m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) + { + nRetVal = UpdateS2DTables(depth); + XN_IS_STATUS_OK(nRetVal); + } + } + + if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) + { + // only after node is ready + XnNodeInfo* pNodeInfo; + if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK) + { + // check this is a depth node + if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_DEPTH) + { + xn::DepthGenerator depth(node); + nRetVal = UpdateRWData(depth); + XN_IS_STATUS_OK(nRetVal); + } + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadRealProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnDouble dValue; + + // read change data + nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &dValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleRealProperty(strModule, strProp, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleRealProperty(const XnChar *strModule, const XnChar *strName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pNotifications->OnNodeRealPropChanged(m_pNotificationsCookie, strModule, strName, dValue); + XN_IS_STATUS_OK(nRetVal); + + XnNodeInfo* pNodeInfo; + + if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0 || + strcmp(strName, XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE) == 0) + { + // only after node is ready + xn::DepthGenerator depth; + if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && + m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) + { + nRetVal = UpdateS2DTables(depth); + XN_IS_STATUS_OK(nRetVal); + } + } + + if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0) + { + // only after node is ready + xn::DepthGenerator depth; + if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && + m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) + { + nRetVal = UpdateRWData(depth); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadStringProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + + // read change data + nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleStringProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleStringProperty(const XnChar *strModule, const XnChar *strName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pNotifications->OnNodeStringPropChanged(m_pNotificationsCookie, strModule, strName, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadGeneralProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnGeneralBuffer gbValue; + + // read change data + nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &gbValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleGeneralProperty(strModule, strProp, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // OpenNI props + if (strcmp(strName, XN_STREAM_PROPERTY_CROPPING) == 0) + { + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_CROPPING, sizeof(XnCropping), gbValue.pData); + } + else + { + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, strName, gbValue.nDataSize, gbValue.pData); + } + + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadStreamData() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnCompressionFormats nCompression; + XnUInt32 nCompressedSize; + nRetVal = m_pDataPacker->ReadStreamDataProps(m_pStreamData, &nCompression, &nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandleStreamData(m_pStreamData, nCompression, nCompressedSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void TransformRGB24ToGrayscale16(XnUInt8* pBuffer, XnUInt32* pnBufferSize) +{ + XnRGB24Pixel* pInput = (XnRGB24Pixel*)pBuffer; + XnRGB24Pixel* pBufferEnd = (XnRGB24Pixel*)(pBuffer + *pnBufferSize); + XnUInt16* pOutput = (XnUInt16*)pBuffer; + + while (pInput < pBufferEnd) + { + *pOutput = ((XnUInt16)pInput->nRed) << 2; + pInput++; + pOutput++; + } + + *pnBufferSize = (XnUInt8*)pOutput - pBuffer; +} + +XnStatus XnFileDevice::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nPosition; + nRetVal = m_pInputStream->Tell(&nPosition); + XN_IS_STATUS_OK(nRetVal); + + XnUIntHash::Iterator it = m_PositionsToIgnore.end(); + if (XN_STATUS_OK == m_PositionsToIgnore.Find(nPosition, it)) + { + // ignore this one. Just update the frame ID + XnNodeInfo* pNodeInfo; + nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + pNodeInfo->nCurrFrameID++; + + // and remove it from list + nRetVal = m_PositionsToIgnore.Remove(it); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // take the codec + XnNodeInfo* pNodeInfo; + nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); + XN_IS_STATUS_OK(nRetVal); + + // now uncompress data + nRetVal = m_pDataPacker->ReadStreamData(pDataProps, pNodeInfo->pXnCodec); + XN_IS_STATUS_OK(nRetVal); + + if (!m_bHighresTimestamps) + { + pDataProps->nTimestamp *= 1000; + } + + if (pNodeInfo->bIRisRGB) + { + // covert RGB IR to regular IR + TransformRGB24ToGrayscale16((XnUInt8*)pDataProps->pData, &pDataProps->nDataSize); + } + + // update curr timestamp + if (pDataProps->nTimestamp > m_nCurrTimestamp) + { + m_nCurrTimestamp = pDataProps->nTimestamp; + } + + // update frame ID + ++pNodeInfo->nCurrFrameID; + + // and notify about new data + nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, pDataProps->StreamName, pDataProps->nTimestamp, pNodeInfo->nCurrFrameID, pDataProps->pData, pDataProps->nDataSize); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::HandleEndOfStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bFileHasData) + { + XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "File does not contain any data..."); + } + + nRetVal = m_eofEvent.Raise(); + XN_IS_STATUS_OK(nRetVal); + + if (m_bRepeat) + { + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + } + else + { + m_bEOF = TRUE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadNextEventFromStream(XnPackedDataType* pnObjectType /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnPackedDataType nObjectType; + + nRetVal = m_pDataPacker->ReadNextObject(&nObjectType); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = HandlePackedObject(nObjectType); + XN_IS_STATUS_OK(nRetVal); + + if (pnObjectType != NULL) + { + *pnObjectType = nObjectType; + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::ReadTillNextData(XnBool* pbWrapOccurred) +{ + XnStatus nRetVal = XN_STATUS_OK; + + *pbWrapOccurred = FALSE; + + if (m_nFileVersion < 4) + { + nRetVal = BCReadFrame(pbWrapOccurred); + XN_IS_STATUS_OK(nRetVal); + } + else + { + XnPackedDataType nType = XN_PACKED_END; + while ((nType != XN_PACKED_STREAM_DATA) && (!m_bEOF)) + { + nRetVal = ReadNextEventFromStream(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_PACKED_END) + { + *pbWrapOccurred = TRUE; + } + } + + if (nType == XN_PACKED_STREAM_DATA) + { + m_bFileHasData = TRUE; + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::Rewind() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // go back to start of stream + nRetVal = m_pInputStream->Seek(XN_DEVICE_FILE_MAGIC_LEN); + XN_IS_STATUS_OK(nRetVal); + + // read initial state + XN_PROPERTY_SET_CREATE_ON_STACK(state); + nRetVal = ReadInitialState(&state); + XN_IS_STATUS_OK(nRetVal); + + // first handle current streams. remove or reset them + for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) + { + const XnChar* strName = it.Key(); + + if (m_bNodeCollectionChanged) + { + // we need to destroy all streams, and recreate them later + nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, strName); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // just reset frame ID + it.Value().nCurrFrameID = 0; + // and mark not to recreate it + nRetVal = m_ignoreNewNodes.Set(strName, it.Value()); + XN_IS_STATUS_OK(nRetVal); + } + } + + // if we need, recreate nodes + if (m_bNodeCollectionChanged) + { + nRetVal = SetInitialState(&state); + XN_IS_STATUS_OK(nRetVal); + } + +// ResetLastTimestampAndFrame(); +// m_nReferenceTimestamp = 0; +// m_nReferenceTime = 0; + + m_bNodeCollectionChanged = FALSE; + m_nCurrTimestamp = 0; + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::UpdateS2DTables(const xn::DepthGenerator& depth) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nTemp; + XnDouble dTemp; + + // get config + XnShiftToDepthConfig config; + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nZeroPlaneDistance = nTemp; + + nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, dTemp); + XN_IS_STATUS_OK(nRetVal); + config.fZeroPlanePixelSize = dTemp; + + nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, dTemp); + XN_IS_STATUS_OK(nRetVal); + config.fEmitterDCmosDistance = dTemp; + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_MAX_SHIFT, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nDeviceMaxShiftValue = nTemp; + + config.nDeviceMaxDepthValue = depth.GetDeviceMaxDepth(); + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_CONST_SHIFT, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nConstShift = nTemp; + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nPixelSizeFactor = nTemp; + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PARAM_COEFF, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nParamCoeff = nTemp; + + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, nTemp); + XN_IS_STATUS_OK(nRetVal); + config.nShiftScale = nTemp; + + config.nDepthMinCutOff = 0; + config.nDepthMaxCutOff = config.nDeviceMaxDepthValue; + + if (!m_ShiftToDepth.bIsInitialized) + { + nRetVal = XnShiftToDepthInit(&m_ShiftToDepth, &config); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nRetVal = XnShiftToDepthUpdate(&m_ShiftToDepth, &config); + XN_IS_STATUS_OK(nRetVal); + } + + // notify + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_S2D_TABLE, m_ShiftToDepth.nShiftsCount * sizeof(XnDepthPixel), m_ShiftToDepth.pShiftToDepthTable); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_D2S_TABLE, m_ShiftToDepth.nDepthsCount * sizeof(XnUInt16), m_ShiftToDepth.pDepthToShiftTable); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::UpdateRWData(const xn::DepthGenerator& depth) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nZPD; + nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nZPD); + XN_IS_STATUS_OK(nRetVal); + + XnDouble fZPPS; + nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, fZPPS); + XN_IS_STATUS_OK(nRetVal); + + XnFieldOfView FOV; + FOV.fHFOV = 2*atan(fZPPS*XN_SXGA_X_RES/2/nZPD); + FOV.fVFOV = 2*atan(fZPPS*XN_VGA_Y_RES*2/2/nZPD); + + // notify + nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, + depth.GetName(), + XN_PROP_FIELD_OF_VIEW, + sizeof(FOV), + &FOV); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceFile/XnFileDevice.h b/Source/XnDeviceFile/XnFileDevice.h index c32a213..ecda90b 100644 --- a/Source/XnDeviceFile/XnFileDevice.h +++ b/Source/XnDeviceFile/XnFileDevice.h @@ -1,155 +1,155 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_DEVICE_H__ -#define __XN_SENSOR_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include "XnDeviceFileReaderBC.h" -#include "XnNiInputStream.h" -#include "XnDeviceFile.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnFileDevice : virtual public xn::ModulePlayer -{ -public: - XnFileDevice(xn::Context& context, const XnChar* strInstanceName); - virtual ~XnFileDevice(); - - XnStatus Init(); - - virtual XnBool IsCapabilitySupported(const XnChar* strCapabilityName) { return FALSE; } - - virtual const XnChar* GetSupportedFormat() { return "XNS"; } - virtual XnStatus SetInputStream(void *pStreamCookie, XnPlayerInputStreamInterface *pStream); - virtual XnStatus ReadNext(); - virtual XnStatus SetNodeNotifications(void *pNodeNotificationsCookie, XnNodeNotifications *pNodeNotifications); - virtual XnStatus SetRepeat(XnBool bRepeat); - virtual XnStatus SeekToTimeStamp(XnInt64 nTimeOffset, XnPlayerSeekOrigin origin); - virtual XnStatus SeekToFrame(const XnChar* strNodeName, XnInt32 nFrameOffset, XnPlayerSeekOrigin origin); - virtual XnStatus TellTimestamp(XnUInt64& nTimestamp); - virtual XnStatus TellFrame(const XnChar* strNodeName, XnUInt32 &nFrameOffset); - virtual XnStatus GetNumFrames(const XnChar* strNodeName, XnUInt32& nFrames); - virtual XnBool IsEOF(); - virtual XnStatus RegisterToEndOfFileReached(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - virtual void UnregisterFromEndOfFileReached(XnCallbackHandle hCallback); - -private: - void Free(); - - XnStatus ReadFileVersion(); - XnStatus ReadNextEventFromStream(XnPackedDataType* pnObjectType = NULL); - XnStatus ReadInitialState(XnPropertySet* pSet); - XnStatus SetInitialState(XnPropertySet* pSet); - XnStatus ReadTillNextData(XnBool* pbWrapOccurred); - - XnStatus HandlePackedObject(XnPackedDataType nObjectType); - XnStatus ReadNewStream(); - XnStatus ReadStreamRemoved(); - XnStatus ReadIntProperty(); - XnStatus ReadRealProperty(); - XnStatus ReadStringProperty(); - XnStatus ReadGeneralProperty(); - XnStatus ReadStreamData(); - XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); - XnStatus HandleStreamRemoved(const XnChar* strName); - XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); - XnStatus HandleRealProperty(const XnChar* strModule, const XnChar* strName, XnDouble dValue); - XnStatus HandleStringProperty(const XnChar* strModule, const XnChar* strName, const XnChar* strValue); - XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); - XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); - XnStatus HandleEndOfStream(); - XnStatus Rewind(); - XnStatus SeekTo(XnUInt64 nMinTimestamp, const XnChar* strNode, XnUInt32 nFrameID); - XnStatus UpdateS2DTables(const xn::DepthGenerator& depth); - XnStatus UpdateRWData(const xn::DepthGenerator& depth); - XnStatus CreateCodec(xn::ProductionNode& node); - XnStatus CheckIRCompatibility(xn::ProductionNode& node); - - // Some BC functions - XnStatus BCSeek(XnUInt64 nTimestamp); - XnStatus BCSeekFrame(XnUInt32 nFrameID); - XnStatus BCInit(); - XnStatus BCCalculatePackedBufferSize(); - XnStatus BCReadInitialState(XnPropertySet* pSet); - XnStatus BCReadFrame(XnBool* pbRewind); - XnStatus BCDestroy(); - - xn::Context m_context; - - XnInputStream* m_pInputStream; - XnDataPacker* m_pDataPacker; - - XnNodeNotifications* m_pNotifications; - void* m_pNotificationsCookie; - - typedef struct XnNodeInfo - { - xn::Codec codec; - XnCodec* pXnCodec; - XnUInt32 nCurrFrameID; - XnBool bIRisRGB; - } XnNodeInfo; - - XN_DECLARE_STRINGS_HASH(XnNodeInfo, XnNodeInfoMap); - XnNodeInfoMap m_nodeInfoMap; - XnNodeInfoMap m_ignoreNewNodes; - - XnBool m_bHighresTimestamps; - XnStreamData* m_pStreamData; - XnBool m_bRepeat; - - XnUInt32 m_nFileVersion; - XnBool m_bFileHasData; - XnBool m_bNodeCollectionChanged; - - XnUInt64 m_nCurrTimestamp; - - XN_DECLARE_DEFAULT_HASH(XnUInt32, XnValue, XnUIntHash); - XnUIntHash m_PositionsToIgnore; // used for seeking - - XN_DECLARE_EVENT_0ARG(XnEOFEvent, IXnEOFEvent); - XnEOFEvent m_eofEvent; - XnBool m_bEOF; - - XnShiftToDepthTables m_ShiftToDepth; - - XnFileBCData* m_pBCData; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_DEVICE_H__ +#define __XN_SENSOR_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include "XnDeviceFileReaderBC.h" +#include "XnNiInputStream.h" +#include "XnDeviceFile.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnFileDevice : virtual public xn::ModulePlayer +{ +public: + XnFileDevice(xn::Context& context, const XnChar* strInstanceName); + virtual ~XnFileDevice(); + + XnStatus Init(); + + virtual XnBool IsCapabilitySupported(const XnChar* strCapabilityName) { return FALSE; } + + virtual const XnChar* GetSupportedFormat() { return "XNS"; } + virtual XnStatus SetInputStream(void *pStreamCookie, XnPlayerInputStreamInterface *pStream); + virtual XnStatus ReadNext(); + virtual XnStatus SetNodeNotifications(void *pNodeNotificationsCookie, XnNodeNotifications *pNodeNotifications); + virtual XnStatus SetRepeat(XnBool bRepeat); + virtual XnStatus SeekToTimeStamp(XnInt64 nTimeOffset, XnPlayerSeekOrigin origin); + virtual XnStatus SeekToFrame(const XnChar* strNodeName, XnInt32 nFrameOffset, XnPlayerSeekOrigin origin); + virtual XnStatus TellTimestamp(XnUInt64& nTimestamp); + virtual XnStatus TellFrame(const XnChar* strNodeName, XnUInt32 &nFrameOffset); + virtual XnStatus GetNumFrames(const XnChar* strNodeName, XnUInt32& nFrames); + virtual XnBool IsEOF(); + virtual XnStatus RegisterToEndOfFileReached(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + virtual void UnregisterFromEndOfFileReached(XnCallbackHandle hCallback); + +private: + void Free(); + + XnStatus ReadFileVersion(); + XnStatus ReadNextEventFromStream(XnPackedDataType* pnObjectType = NULL); + XnStatus ReadInitialState(XnPropertySet* pSet); + XnStatus SetInitialState(XnPropertySet* pSet); + XnStatus ReadTillNextData(XnBool* pbWrapOccurred); + + XnStatus HandlePackedObject(XnPackedDataType nObjectType); + XnStatus ReadNewStream(); + XnStatus ReadStreamRemoved(); + XnStatus ReadIntProperty(); + XnStatus ReadRealProperty(); + XnStatus ReadStringProperty(); + XnStatus ReadGeneralProperty(); + XnStatus ReadStreamData(); + XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); + XnStatus HandleStreamRemoved(const XnChar* strName); + XnStatus HandleIntProperty(const XnChar* strModule, const XnChar* strName, XnUInt64 nValue); + XnStatus HandleRealProperty(const XnChar* strModule, const XnChar* strName, XnDouble dValue); + XnStatus HandleStringProperty(const XnChar* strModule, const XnChar* strName, const XnChar* strValue); + XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); + XnStatus HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats nCompression, XnUInt32 nCompressedSize); + XnStatus HandleEndOfStream(); + XnStatus Rewind(); + XnStatus SeekTo(XnUInt64 nMinTimestamp, const XnChar* strNode, XnUInt32 nFrameID); + XnStatus UpdateS2DTables(const xn::DepthGenerator& depth); + XnStatus UpdateRWData(const xn::DepthGenerator& depth); + XnStatus CreateCodec(xn::ProductionNode& node); + XnStatus CheckIRCompatibility(xn::ProductionNode& node); + + // Some BC functions + XnStatus BCSeek(XnUInt64 nTimestamp); + XnStatus BCSeekFrame(XnUInt32 nFrameID); + XnStatus BCInit(); + XnStatus BCCalculatePackedBufferSize(); + XnStatus BCReadInitialState(XnPropertySet* pSet); + XnStatus BCReadFrame(XnBool* pbRewind); + XnStatus BCDestroy(); + + xn::Context m_context; + + XnInputStream* m_pInputStream; + XnDataPacker* m_pDataPacker; + + XnNodeNotifications* m_pNotifications; + void* m_pNotificationsCookie; + + typedef struct XnNodeInfo + { + xn::Codec codec; + XnCodec* pXnCodec; + XnUInt32 nCurrFrameID; + XnBool bIRisRGB; + } XnNodeInfo; + + XN_DECLARE_STRINGS_HASH(XnNodeInfo, XnNodeInfoMap); + XnNodeInfoMap m_nodeInfoMap; + XnNodeInfoMap m_ignoreNewNodes; + + XnBool m_bHighresTimestamps; + XnStreamData* m_pStreamData; + XnBool m_bRepeat; + + XnUInt32 m_nFileVersion; + XnBool m_bFileHasData; + XnBool m_bNodeCollectionChanged; + + XnUInt64 m_nCurrTimestamp; + + XN_DECLARE_DEFAULT_HASH(XnUInt32, XnValue, XnUIntHash); + XnUIntHash m_PositionsToIgnore; // used for seeking + + XN_DECLARE_EVENT_0ARG(XnEOFEvent, IXnEOFEvent); + XnEOFEvent m_eofEvent; + XnBool m_bEOF; + + XnShiftToDepthTables m_ShiftToDepth; + + XnFileBCData* m_pBCData; +}; + #endif // __XN_SENSOR_DEVICE_H__ \ No newline at end of file diff --git a/Source/XnDeviceFile/XnFileDeviceBC.cpp b/Source/XnDeviceFile/XnFileDeviceBC.cpp index 2795a63..af2fa59 100644 --- a/Source/XnDeviceFile/XnFileDeviceBC.cpp +++ b/Source/XnDeviceFile/XnFileDeviceBC.cpp @@ -1,637 +1,637 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - -#include "XnFileDevice.h" -#include "XnDeviceFileReaderBC.h" -#include -#include -#include - -//--------------------------------------------------------------------------- -// Backwards Compatibility -//--------------------------------------------------------------------------- - -extern XnStatus XnIOAdjustStreamPropertiesV3(const XnStreamProperties* pStreamPropertiesV3, XnStreamProperties* pStreamProperties); -extern XnStatus XnIOAdjustStreamPropertiesV2 (const XnStreamPropertiesV2* pStreamPropertiesV2, XnStreamProperties* pStreamProperties); -extern XnStatus XnIOAdjustStreamPropertiesV1 (const XnStreamPropertiesV1* pStreamPropertiesV1, XnStreamProperties* pStreamProperties); -extern XnStatus XnIOAdjustStreamFramePropertiesV3(const XnStreamFrameProperties* pStreamFramePropertiesV3, XnStreamFrameProperties* pStreamFrameProperties); -extern XnStatus XnIOAdjustStreamFramePropertiesV2 (const XnStreamFramePropertiesV2* pStreamFramePropertiesV2, XnStreamFrameProperties* pStreamFrameProperties); -extern XnStatus XnIOAdjustStreamFramePropertiesV1 (const XnStreamFramePropertiesV1* pStreamFramePropertiesV1, XnStreamFrameProperties* pStreamFrameProperties); -extern XnStatus XnIOAdjustPackedStreamPropertiesV2 (const XnPackedStreamPropertiesV2* pPackedStreamPropertiesV2, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus XnIOAdjustPackedStreamFrameHeaderV2 (const XnPackedStreamFrameHeaderV2* pPackedStreamFrameHeaderV2, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); -extern XnStatus XnIOAdjustPackedStreamPropertiesV1 (const XnPackedStreamPropertiesV1* pPackedStreamPropertiesV1, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus XnIOAdjustPackedStreamFrameHeaderV1 (const XnPackedStreamFrameHeaderV1* pPackedStreamFrameHeaderV1, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); -extern XnStatus XnIOAdjustPackedStreamPropertiesV3 (const XnPackedStreamProperties* pPackedStreamPropertiesV3, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus XnIOAdjustPackedStreamFrameHeaderV3 (const XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeaderV3, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); -extern XnStatus BCSetDepthProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus BCSetImageProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus BCSetAudioProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); -extern XnStatus ConvertStreamPropertiesToPropertySet(XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties, XnPropertySet* pSet); -extern XnStatus XnDeviceFileAdjustFileFrameHeaderV1(const XnDeviceFileFrameHeaderV1* pFileFrameHeaderV1, XnDeviceFileFrameHeaderV3* pFileFrameHeader); -extern XnStatus XnDeviceFileAdjustFileFrameHeaderV2(const XnDeviceFileFrameHeaderV2* pFileFrameHeaderV2, XnDeviceFileFrameHeaderV3* pFileFrameHeader); -extern XnStatus XnDeviceFileAdjustFileFrameHeaderV3(const XnDeviceFileFrameHeaderV3* pFileFrameHeaderV3, XnDeviceFileFrameHeaderV3* pFileFrameHeader); - -XnStatus XnFileDevice::BCInit() -{ - XN_VALIDATE_CALLOC(m_pBCData, XnFileBCData, 1); - return XN_STATUS_OK; -} - -XnStatus XnFileDevice::BCCalculatePackedBufferSize() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamPropertiesV3* pStreamProperties = &m_pBCData->StreamProperties; - XnPackedStreamProperties* pPackedStreamProperties = &m_pBCData->PackedStreamProperties; - - XnUInt32 nBufferSize = 0; - - if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED) - { - if ((pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW12) || - (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW10) || - (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_SHIFTS)) - { - switch (pPackedStreamProperties->StreamDepthCompressionFormat) - { - case XN_COMPRESSED_DEPTH_FORMAT_SKIP: - break; - case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nDepthBufferSize; - break; - case XN_COMPRESSED_DEPTH_FORMAT_16Z: - case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: - nBufferSize += (XnUInt32)(pStreamProperties->nDepthBufferSize * XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT); - } - } - - if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED) - { - if ((pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_RGB24) || (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_GRAYSCALE8)) - { - switch (pPackedStreamProperties->StreamImageCompressionFormat) - { - case XN_COMPRESSED_IMAGE_FORMAT_SKIP: - break; - case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nImageBufferSize; - break; - case XN_COMPRESSED_IMAGE_FORMAT_8Z: - nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO); - break; - case XN_COMPRESSED_IMAGE_FORMAT_JPEG: - nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); - } - } - else if (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_YUV422) - { - switch (pPackedStreamProperties->StreamImageCompressionFormat) - { - case XN_COMPRESSED_IMAGE_FORMAT_SKIP: - break; - case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nImageBufferSize; - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT); - } - } - - if (pStreamProperties->MiscFormat != XN_MISC_FORMAT_DISABLED) - { - if (pStreamProperties->MiscFormat == XN_MISC_FORMAT_CONFIDENCE_MAP) - { - switch (pPackedStreamProperties->StreamMiscCompressionFormat) - { - case XN_COMPRESSED_MISC_FORMAT_SKIP: - break; - case XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nMiscBufferSize; - break; - case XN_COMPRESSED_MISC_FORMAT_CONF4: - nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); - break; - case XN_COMPRESSED_MISC_FORMAT_CONF4LZ: - nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT); - } - } - - if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED) - { - if (pStreamProperties->AudioFormat == XN_AUDIO_FORMAT_PCM) - { - switch (pPackedStreamProperties->StreamAudioCompressionFormat) - { - case XN_COMPRESSED_AUDIO_FORMAT_SKIP: - break; - case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: - nBufferSize += pStreamProperties->nAudioBufferSize; - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT); - } - } - else - { - return (XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT); - } - } - - nBufferSize += sizeof(XnPackedStreamFrameHeaderV3); - - return nBufferSize; - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::BCReadInitialState(XnPropertySet* pSet) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - XnDeviceFileHeader DeviceFileHeader; - XN_STREAM_FLAGS_TYPE nStreamFlags = 0; - - m_pBCData->nFramePos = 1; - - m_pBCData->pPackedStreamBuffer = NULL; - m_pBCData->nPackedStreamBufferSize = 0; - - // read StreamProperties - if (m_nFileVersion == 3) - { - // Current Version - nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.nMajorVersion, sizeof(XnUInt16)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.nMinorVersion, sizeof(XnUInt16)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.StreamProperties, sizeof(XnStreamPropertiesV3)); - XN_IS_STATUS_OK(nRetVal); - - DeviceFileHeader.nMajorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMajorVersion); - DeviceFileHeader.nMinorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMinorVersion); - - nRetVal = XnIOAdjustStreamPropertiesV3(&DeviceFileHeader.StreamProperties, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else if (m_nFileVersion == 2) - { - // Version 2 - DeviceFileHeader.nMajorVersion = 0; - DeviceFileHeader.nMinorVersion = 0; - XnStreamPropertiesV2 StreamPropertiesV2; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&StreamPropertiesV2, sizeof(XnStreamPropertiesV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else if (m_nFileVersion == 1) - { - // Version 1 - DeviceFileHeader.nMajorVersion = 0; - DeviceFileHeader.nMinorVersion = 0; - XnStreamPropertiesV1 StreamPropertiesV1; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&StreamPropertiesV1, sizeof(XnStreamPropertiesV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustStreamPropertiesV1(&StreamPropertiesV1, &DeviceFileHeader.StreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // Bad Magic - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // read packed stream properties - switch (m_nFileVersion) - { - case 3: - { - nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV3(&DeviceFileHeader.PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 2: - { - XnPackedStreamPropertiesV2 PackedStreamPropertiesV2; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&PackedStreamPropertiesV2, sizeof(XnPackedStreamPropertiesV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV2(&PackedStreamPropertiesV2, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 1: - { - XnPackedStreamPropertiesV1 PackedStreamPropertiesV1; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&PackedStreamPropertiesV1, sizeof(XnPackedStreamPropertiesV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIOAdjustPackedStreamPropertiesV1(&PackedStreamPropertiesV1, &DeviceFileHeader.PackedStreamProperties); - XN_IS_STATUS_OK(nRetVal); - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Save the stream properties into the private data (but keep the original stream flags) - nStreamFlags = m_pBCData->StreamProperties.nStreamFlags; - xnOSMemCopy(&m_pBCData->StreamProperties, &DeviceFileHeader.StreamProperties, sizeof(XnStreamProperties)); - m_pBCData->StreamProperties.nStreamFlags = nStreamFlags; - - if (m_pBCData->StreamProperties.Shift2DepthData.bShift2DepthData) - { - m_pBCData->StreamProperties.Shift2DepthData.nMaxDepthValue = 10000; - m_pBCData->StreamProperties.nDepthMaxValue = 10000; - } - - // Save the packed stream properties into the private data - xnOSMemCopy(&m_pBCData->PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); - - XnUInt32 nBufferSize = BCCalculatePackedBufferSize(); - if (nBufferSize != m_pBCData->nPackedStreamBufferSize) - { - xnOSFree(m_pBCData->pPackedStreamBuffer); - XN_VALIDATE_ALIGNED_CALLOC(m_pBCData->pPackedStreamBuffer, XnUChar, nBufferSize, XN_DEFAULT_MEM_ALIGN); - m_pBCData->nPackedStreamBufferSize = nBufferSize; - } - - nRetVal = ConvertStreamPropertiesToPropertySet(&m_pBCData->StreamProperties, &m_pBCData->PackedStreamProperties, pSet); - XN_IS_STATUS_OK(nRetVal); - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::BCSeek(XnUInt64 nTimestamp) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnFileDevice::BCSeekFrame(XnUInt32 nFrameID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceFileFrameHeaderV3 FileFrameHeader; - XnUInt32 nReadBytes = 0; - XnUInt32 nShouldRead = 0; - XnInt32 nExpectedFrameID = 1; - - // go back to start of file - nRetVal = Rewind(); - XN_IS_STATUS_OK(nRetVal); - - // Update the frame position to the new position (treat 0 as 1) - m_pBCData->nFramePos = XN_MAX(nFrameID, 1); - - // Make sure we aren't trying to reach a frame that's beyond the number of frames - if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) - { - // Set the frame position to the last frame - m_pBCData->nFramePos = m_pBCData->StreamProperties.nNumOfFrames; - } - - // Set the file position to the first frame data (right after the file header) - XnUInt32 nOffset = 0; - switch (m_nFileVersion) - { - case 3: - nOffset = sizeof(XnDeviceFileHeader); - break; - case 2: - nOffset = sizeof(XnDeviceFileHeaderV2); - break; - case 1: - nOffset = sizeof(XnDeviceFileHeaderV1); - break; - default: - return (XN_STATUS_IO_INVALID_STREAM_HEADER); - } - - nRetVal = m_pInputStream->Seek(nOffset); - XN_IS_STATUS_OK(nRetVal); - - // If the wanted position was the first frame, we're already there - if (m_pBCData->nFramePos == 1) - { - return (XN_STATUS_OK); - } - - // Keep reading frames until we reach the wanted frame - XnUInt32 nCurrFilePos = 1; - while (nCurrFilePos < m_pBCData->nFramePos) - { - // Read the frame header - switch (m_nFileVersion) - { - case 3: - { - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV3); - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeader, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos; - } - break; - case 2: - { - XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV2); - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV2, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos - 1; - } - break; - case 1: - { - XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; - nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV1); - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV1, nReadBytes); - XN_IS_STATUS_OK(nRetVal); - nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - nExpectedFrameID = nCurrFilePos - 1; - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Make sure we got the right header size - if (nReadBytes != nShouldRead) - { - return (XN_STATUS_IO_INVALID_STREAM_FRAME_HEADER); - } - - // Skip the frame data - XnUInt32 nPosition; - nRetVal = m_pInputStream->Tell(&nPosition); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pInputStream->Seek(FileFrameHeader.nPackedStreamSize + nPosition); - XN_IS_STATUS_OK(nRetVal); - - // increment streams frame ID - for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) - { - it.Value().nCurrFrameID++; - } - - // Make sure frame ids are sequential - if (FileFrameHeader.FrameProperties.nDepthFrameID != nExpectedFrameID) - { - return (XN_STATUS_IO_STREAM_NOT_SEQUENTIAL); - } - - // Update the current file frame position - nCurrFilePos++; - } - - // now read last frame (the one we wanted) - XnBool bWrapOccured; - nRetVal = BCReadFrame(&bWrapOccured); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::BCReadFrame(XnBool* pbWrapOccured) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - XnDeviceFileFrameHeaderV3 FileFrameHeader; - XnUInt64 nCurrTime = 0; - XnUInt64 nDiffTime = 0; - XnUInt64 nFramesDiffTime = 0; - XnUInt32 nSleepTime = 0; - - *pbWrapOccured = FALSE; - - // If we've reached the last frame, seek back to the first one - if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) - { - nRetVal = HandleEndOfStream(); - XN_IS_STATUS_OK(nRetVal); - *pbWrapOccured = TRUE; - if (m_bEOF) - { - return XN_STATUS_OK; - } - } - - m_bFileHasData = TRUE; - - // Note: Since this is an internal function, the pointers are assumed to be checked by the caller - // Read the frame header - switch (m_nFileVersion) - { - case 3: - { - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeader, sizeof(XnDeviceFileFrameHeaderV3)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV3(&FileFrameHeader, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 2: - { - XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV2, sizeof(XnDeviceFileFrameHeaderV2)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - case 1: - { - XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; - - nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV1, sizeof(XnDeviceFileFrameHeaderV1)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); - XN_IS_STATUS_OK(nRetVal); - } - break; - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - FileFrameHeader.FrameProperties.nDepthFrameID = m_pBCData->nFramePos; - FileFrameHeader.FrameProperties.nImageFrameID = m_pBCData->nFramePos; - - // Make sure we aren't going to overflow the packed stream buffer - if (FileFrameHeader.nPackedStreamSize > m_pBCData->nPackedStreamBufferSize) - { - return (XN_STATUS_INPUT_BUFFER_OVERFLOW); - } - - // Read the frame packed stream data into the packed stream buffer - nRetVal = m_pInputStream->ReadData(m_pBCData->pPackedStreamBuffer, FileFrameHeader.nPackedStreamSize); - XN_IS_STATUS_OK(nRetVal); - - // read the frame header - XnPackedStreamFrameHeaderV3 PackedStreamHeader; - XnUChar* pPackedBuffer = m_pBCData->pPackedStreamBuffer; - - switch (m_nFileVersion) - { - case 0: - case 3: - { - xnOSMemCopy(&PackedStreamHeader, pPackedBuffer, sizeof(XnPackedStreamFrameHeaderV3)); - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV3); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV3(&PackedStreamHeader, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - case 2: - { - XnPackedStreamFrameHeaderV2* pPackedStreamHeaderV2 = (XnPackedStreamFrameHeaderV2*)pPackedBuffer; - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV2); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamHeaderV2, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - case 1: - { - XnPackedStreamFrameHeaderV1* pPackedStreamHeaderV1 = (XnPackedStreamFrameHeaderV1*)pPackedBuffer; - pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV1); - nRetVal = XnIOAdjustPackedStreamFrameHeaderV1(pPackedStreamHeaderV1, &PackedStreamHeader); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - return XN_STATUS_IO_INVALID_STREAM_HEADER; - } - - // Depth - XnNodeInfo* pNodeInfo; - if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_DEPTH, pNodeInfo)) - { - m_pStreamData->nDataSize = m_pBCData->StreamProperties.nDepthBufferSize; - - nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompDepthBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_DEPTH, FileFrameHeader.FrameProperties.nDepthTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pBCData->StreamProperties.nDepthBufferSize); - XN_IS_STATUS_OK(nRetVal); - - pNodeInfo->nCurrFrameID++; - - pPackedBuffer += PackedStreamHeader.nCompDepthBufferSize; - } - - // Image - if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_IMAGE, pNodeInfo)) - { - m_pStreamData->nDataSize = m_pBCData->StreamProperties.nImageBufferSize; - - nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompImageBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_IMAGE, FileFrameHeader.FrameProperties.nImageTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pBCData->StreamProperties.nImageBufferSize); - XN_IS_STATUS_OK(nRetVal); - - pNodeInfo->nCurrFrameID++; - - pPackedBuffer += PackedStreamHeader.nCompImageBufferSize; - } - - // we do not support MISC - pPackedBuffer += PackedStreamHeader.nCompMiscBufferSize; - - // Audio - if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_AUDIO, pNodeInfo)) - { - m_pStreamData->nDataSize = m_pBCData->StreamProperties.nAudioBufferSize; - - nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompAudioBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_AUDIO, FileFrameHeader.FrameProperties.nAudioTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pStreamData->nDataSize); - XN_IS_STATUS_OK(nRetVal); - - pNodeInfo->nCurrFrameID++; - - pPackedBuffer += PackedStreamHeader.nCompAudioBufferSize; - } - - // Increase the file frame position - m_pBCData->nFramePos++; - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnFileDevice::BCDestroy() -{ - if (m_pBCData != NULL) - { - xnOSFreeAligned(m_pBCData->pPackedStreamBuffer); - xnOSFree(m_pBCData); - } - - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + +#include "XnFileDevice.h" +#include "XnDeviceFileReaderBC.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// Backwards Compatibility +//--------------------------------------------------------------------------- + +extern XnStatus XnIOAdjustStreamPropertiesV3(const XnStreamProperties* pStreamPropertiesV3, XnStreamProperties* pStreamProperties); +extern XnStatus XnIOAdjustStreamPropertiesV2 (const XnStreamPropertiesV2* pStreamPropertiesV2, XnStreamProperties* pStreamProperties); +extern XnStatus XnIOAdjustStreamPropertiesV1 (const XnStreamPropertiesV1* pStreamPropertiesV1, XnStreamProperties* pStreamProperties); +extern XnStatus XnIOAdjustStreamFramePropertiesV3(const XnStreamFrameProperties* pStreamFramePropertiesV3, XnStreamFrameProperties* pStreamFrameProperties); +extern XnStatus XnIOAdjustStreamFramePropertiesV2 (const XnStreamFramePropertiesV2* pStreamFramePropertiesV2, XnStreamFrameProperties* pStreamFrameProperties); +extern XnStatus XnIOAdjustStreamFramePropertiesV1 (const XnStreamFramePropertiesV1* pStreamFramePropertiesV1, XnStreamFrameProperties* pStreamFrameProperties); +extern XnStatus XnIOAdjustPackedStreamPropertiesV2 (const XnPackedStreamPropertiesV2* pPackedStreamPropertiesV2, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus XnIOAdjustPackedStreamFrameHeaderV2 (const XnPackedStreamFrameHeaderV2* pPackedStreamFrameHeaderV2, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); +extern XnStatus XnIOAdjustPackedStreamPropertiesV1 (const XnPackedStreamPropertiesV1* pPackedStreamPropertiesV1, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus XnIOAdjustPackedStreamFrameHeaderV1 (const XnPackedStreamFrameHeaderV1* pPackedStreamFrameHeaderV1, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); +extern XnStatus XnIOAdjustPackedStreamPropertiesV3 (const XnPackedStreamProperties* pPackedStreamPropertiesV3, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus XnIOAdjustPackedStreamFrameHeaderV3 (const XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeaderV3, XnPackedStreamFrameHeaderV3* pPackedStreamFrameHeader); +extern XnStatus BCSetDepthProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus BCSetImageProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus BCSetAudioProperties(XnPropertySet* pSet, XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties); +extern XnStatus ConvertStreamPropertiesToPropertySet(XnStreamPropertiesV3* pStreamProperties, XnPackedStreamProperties* pPackedStreamProperties, XnPropertySet* pSet); +extern XnStatus XnDeviceFileAdjustFileFrameHeaderV1(const XnDeviceFileFrameHeaderV1* pFileFrameHeaderV1, XnDeviceFileFrameHeaderV3* pFileFrameHeader); +extern XnStatus XnDeviceFileAdjustFileFrameHeaderV2(const XnDeviceFileFrameHeaderV2* pFileFrameHeaderV2, XnDeviceFileFrameHeaderV3* pFileFrameHeader); +extern XnStatus XnDeviceFileAdjustFileFrameHeaderV3(const XnDeviceFileFrameHeaderV3* pFileFrameHeaderV3, XnDeviceFileFrameHeaderV3* pFileFrameHeader); + +XnStatus XnFileDevice::BCInit() +{ + XN_VALIDATE_CALLOC(m_pBCData, XnFileBCData, 1); + return XN_STATUS_OK; +} + +XnStatus XnFileDevice::BCCalculatePackedBufferSize() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamPropertiesV3* pStreamProperties = &m_pBCData->StreamProperties; + XnPackedStreamProperties* pPackedStreamProperties = &m_pBCData->PackedStreamProperties; + + XnUInt32 nBufferSize = 0; + + if (pStreamProperties->DepthFormat != XN_DEPTH_FORMAT_DISABLED) + { + if ((pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW12) || + (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_RAW10) || + (pStreamProperties->DepthFormat == XN_DEPTH_FORMAT_SHIFTS)) + { + switch (pPackedStreamProperties->StreamDepthCompressionFormat) + { + case XN_COMPRESSED_DEPTH_FORMAT_SKIP: + break; + case XN_COMPRESSED_DEPTH_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nDepthBufferSize; + break; + case XN_COMPRESSED_DEPTH_FORMAT_16Z: + case XN_COMPRESSED_DEPTH_FORMAT_16ZEMBTABLE: + nBufferSize += (XnUInt32)(pStreamProperties->nDepthBufferSize * XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_DEPTH_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT); + } + } + + if (pStreamProperties->ImageFormat != XN_IMAGE_FORMAT_DISABLED) + { + if ((pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_RGB24) || (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_GRAYSCALE8)) + { + switch (pPackedStreamProperties->StreamImageCompressionFormat) + { + case XN_COMPRESSED_IMAGE_FORMAT_SKIP: + break; + case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nImageBufferSize; + break; + case XN_COMPRESSED_IMAGE_FORMAT_8Z: + nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO); + break; + case XN_COMPRESSED_IMAGE_FORMAT_JPEG: + nBufferSize += (XnUInt32)(pStreamProperties->nImageBufferSize * XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); + } + } + else if (pStreamProperties->ImageFormat == XN_IMAGE_FORMAT_YUV422) + { + switch (pPackedStreamProperties->StreamImageCompressionFormat) + { + case XN_COMPRESSED_IMAGE_FORMAT_SKIP: + break; + case XN_COMPRESSED_IMAGE_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nImageBufferSize; + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT); + } + } + + if (pStreamProperties->MiscFormat != XN_MISC_FORMAT_DISABLED) + { + if (pStreamProperties->MiscFormat == XN_MISC_FORMAT_CONFIDENCE_MAP) + { + switch (pPackedStreamProperties->StreamMiscCompressionFormat) + { + case XN_COMPRESSED_MISC_FORMAT_SKIP: + break; + case XN_COMPRESSED_MISC_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nMiscBufferSize; + break; + case XN_COMPRESSED_MISC_FORMAT_CONF4: + nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); + break; + case XN_COMPRESSED_MISC_FORMAT_CONF4LZ: + nBufferSize += (XnUInt32)(pStreamProperties->nMiscBufferSize * XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_MISC_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_MISC_FORMAT); + } + } + + if (pStreamProperties->AudioFormat != XN_AUDIO_FORMAT_DISABLED) + { + if (pStreamProperties->AudioFormat == XN_AUDIO_FORMAT_PCM) + { + switch (pPackedStreamProperties->StreamAudioCompressionFormat) + { + case XN_COMPRESSED_AUDIO_FORMAT_SKIP: + break; + case XN_COMPRESSED_AUDIO_FORMAT_UNCOMPRESSED: + nBufferSize += pStreamProperties->nAudioBufferSize; + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_AUDIO_COMPRESSION_FORMAT); + } + } + else + { + return (XN_STATUS_IO_INVALID_STREAM_AUDIO_FORMAT); + } + } + + nBufferSize += sizeof(XnPackedStreamFrameHeaderV3); + + return nBufferSize; + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::BCReadInitialState(XnPropertySet* pSet) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + XnDeviceFileHeader DeviceFileHeader; + XN_STREAM_FLAGS_TYPE nStreamFlags = 0; + + m_pBCData->nFramePos = 1; + + m_pBCData->pPackedStreamBuffer = NULL; + m_pBCData->nPackedStreamBufferSize = 0; + + // read StreamProperties + if (m_nFileVersion == 3) + { + // Current Version + nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.nMajorVersion, sizeof(XnUInt16)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.nMinorVersion, sizeof(XnUInt16)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.StreamProperties, sizeof(XnStreamPropertiesV3)); + XN_IS_STATUS_OK(nRetVal); + + DeviceFileHeader.nMajorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMajorVersion); + DeviceFileHeader.nMinorVersion = XN_PREPARE_VAR16_IN_BUFFER(DeviceFileHeader.nMinorVersion); + + nRetVal = XnIOAdjustStreamPropertiesV3(&DeviceFileHeader.StreamProperties, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else if (m_nFileVersion == 2) + { + // Version 2 + DeviceFileHeader.nMajorVersion = 0; + DeviceFileHeader.nMinorVersion = 0; + XnStreamPropertiesV2 StreamPropertiesV2; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&StreamPropertiesV2, sizeof(XnStreamPropertiesV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustStreamPropertiesV2(&StreamPropertiesV2, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else if (m_nFileVersion == 1) + { + // Version 1 + DeviceFileHeader.nMajorVersion = 0; + DeviceFileHeader.nMinorVersion = 0; + XnStreamPropertiesV1 StreamPropertiesV1; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&StreamPropertiesV1, sizeof(XnStreamPropertiesV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustStreamPropertiesV1(&StreamPropertiesV1, &DeviceFileHeader.StreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // Bad Magic + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // read packed stream properties + switch (m_nFileVersion) + { + case 3: + { + nRetVal = m_pInputStream->ReadData((XnUChar*)&DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV3(&DeviceFileHeader.PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 2: + { + XnPackedStreamPropertiesV2 PackedStreamPropertiesV2; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&PackedStreamPropertiesV2, sizeof(XnPackedStreamPropertiesV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV2(&PackedStreamPropertiesV2, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 1: + { + XnPackedStreamPropertiesV1 PackedStreamPropertiesV1; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&PackedStreamPropertiesV1, sizeof(XnPackedStreamPropertiesV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIOAdjustPackedStreamPropertiesV1(&PackedStreamPropertiesV1, &DeviceFileHeader.PackedStreamProperties); + XN_IS_STATUS_OK(nRetVal); + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Save the stream properties into the private data (but keep the original stream flags) + nStreamFlags = m_pBCData->StreamProperties.nStreamFlags; + xnOSMemCopy(&m_pBCData->StreamProperties, &DeviceFileHeader.StreamProperties, sizeof(XnStreamProperties)); + m_pBCData->StreamProperties.nStreamFlags = nStreamFlags; + + if (m_pBCData->StreamProperties.Shift2DepthData.bShift2DepthData) + { + m_pBCData->StreamProperties.Shift2DepthData.nMaxDepthValue = 10000; + m_pBCData->StreamProperties.nDepthMaxValue = 10000; + } + + // Save the packed stream properties into the private data + xnOSMemCopy(&m_pBCData->PackedStreamProperties, &DeviceFileHeader.PackedStreamProperties, sizeof(XnPackedStreamProperties)); + + XnUInt32 nBufferSize = BCCalculatePackedBufferSize(); + if (nBufferSize != m_pBCData->nPackedStreamBufferSize) + { + xnOSFree(m_pBCData->pPackedStreamBuffer); + XN_VALIDATE_ALIGNED_CALLOC(m_pBCData->pPackedStreamBuffer, XnUChar, nBufferSize, XN_DEFAULT_MEM_ALIGN); + m_pBCData->nPackedStreamBufferSize = nBufferSize; + } + + nRetVal = ConvertStreamPropertiesToPropertySet(&m_pBCData->StreamProperties, &m_pBCData->PackedStreamProperties, pSet); + XN_IS_STATUS_OK(nRetVal); + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::BCSeek(XnUInt64 nTimestamp) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnFileDevice::BCSeekFrame(XnUInt32 nFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceFileFrameHeaderV3 FileFrameHeader; + XnUInt32 nReadBytes = 0; + XnUInt32 nShouldRead = 0; + XnInt32 nExpectedFrameID = 1; + + // go back to start of file + nRetVal = Rewind(); + XN_IS_STATUS_OK(nRetVal); + + // Update the frame position to the new position (treat 0 as 1) + m_pBCData->nFramePos = XN_MAX(nFrameID, 1); + + // Make sure we aren't trying to reach a frame that's beyond the number of frames + if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) + { + // Set the frame position to the last frame + m_pBCData->nFramePos = m_pBCData->StreamProperties.nNumOfFrames; + } + + // Set the file position to the first frame data (right after the file header) + XnUInt32 nOffset = 0; + switch (m_nFileVersion) + { + case 3: + nOffset = sizeof(XnDeviceFileHeader); + break; + case 2: + nOffset = sizeof(XnDeviceFileHeaderV2); + break; + case 1: + nOffset = sizeof(XnDeviceFileHeaderV1); + break; + default: + return (XN_STATUS_IO_INVALID_STREAM_HEADER); + } + + nRetVal = m_pInputStream->Seek(nOffset); + XN_IS_STATUS_OK(nRetVal); + + // If the wanted position was the first frame, we're already there + if (m_pBCData->nFramePos == 1) + { + return (XN_STATUS_OK); + } + + // Keep reading frames until we reach the wanted frame + XnUInt32 nCurrFilePos = 1; + while (nCurrFilePos < m_pBCData->nFramePos) + { + // Read the frame header + switch (m_nFileVersion) + { + case 3: + { + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV3); + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeader, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos; + } + break; + case 2: + { + XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV2); + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV2, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos - 1; + } + break; + case 1: + { + XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; + nShouldRead = nReadBytes = sizeof(XnDeviceFileFrameHeaderV1); + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV1, nReadBytes); + XN_IS_STATUS_OK(nRetVal); + nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + nExpectedFrameID = nCurrFilePos - 1; + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Make sure we got the right header size + if (nReadBytes != nShouldRead) + { + return (XN_STATUS_IO_INVALID_STREAM_FRAME_HEADER); + } + + // Skip the frame data + XnUInt32 nPosition; + nRetVal = m_pInputStream->Tell(&nPosition); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pInputStream->Seek(FileFrameHeader.nPackedStreamSize + nPosition); + XN_IS_STATUS_OK(nRetVal); + + // increment streams frame ID + for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.begin(); it != m_nodeInfoMap.end(); ++it) + { + it.Value().nCurrFrameID++; + } + + // Make sure frame ids are sequential + if (FileFrameHeader.FrameProperties.nDepthFrameID != nExpectedFrameID) + { + return (XN_STATUS_IO_STREAM_NOT_SEQUENTIAL); + } + + // Update the current file frame position + nCurrFilePos++; + } + + // now read last frame (the one we wanted) + XnBool bWrapOccured; + nRetVal = BCReadFrame(&bWrapOccured); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::BCReadFrame(XnBool* pbWrapOccured) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + XnDeviceFileFrameHeaderV3 FileFrameHeader; + XnUInt64 nCurrTime = 0; + XnUInt64 nDiffTime = 0; + XnUInt64 nFramesDiffTime = 0; + XnUInt32 nSleepTime = 0; + + *pbWrapOccured = FALSE; + + // If we've reached the last frame, seek back to the first one + if (m_pBCData->nFramePos > m_pBCData->StreamProperties.nNumOfFrames) + { + nRetVal = HandleEndOfStream(); + XN_IS_STATUS_OK(nRetVal); + *pbWrapOccured = TRUE; + if (m_bEOF) + { + return XN_STATUS_OK; + } + } + + m_bFileHasData = TRUE; + + // Note: Since this is an internal function, the pointers are assumed to be checked by the caller + // Read the frame header + switch (m_nFileVersion) + { + case 3: + { + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeader, sizeof(XnDeviceFileFrameHeaderV3)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV3(&FileFrameHeader, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 2: + { + XnDeviceFileFrameHeaderV2 FileFrameHeaderV2; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV2, sizeof(XnDeviceFileFrameHeaderV2)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV2(&FileFrameHeaderV2, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + case 1: + { + XnDeviceFileFrameHeaderV1 FileFrameHeaderV1; + + nRetVal = m_pInputStream->ReadData((XnUChar*)&FileFrameHeaderV1, sizeof(XnDeviceFileFrameHeaderV1)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceFileAdjustFileFrameHeaderV1(&FileFrameHeaderV1, &FileFrameHeader); + XN_IS_STATUS_OK(nRetVal); + } + break; + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + FileFrameHeader.FrameProperties.nDepthFrameID = m_pBCData->nFramePos; + FileFrameHeader.FrameProperties.nImageFrameID = m_pBCData->nFramePos; + + // Make sure we aren't going to overflow the packed stream buffer + if (FileFrameHeader.nPackedStreamSize > m_pBCData->nPackedStreamBufferSize) + { + return (XN_STATUS_INPUT_BUFFER_OVERFLOW); + } + + // Read the frame packed stream data into the packed stream buffer + nRetVal = m_pInputStream->ReadData(m_pBCData->pPackedStreamBuffer, FileFrameHeader.nPackedStreamSize); + XN_IS_STATUS_OK(nRetVal); + + // read the frame header + XnPackedStreamFrameHeaderV3 PackedStreamHeader; + XnUChar* pPackedBuffer = m_pBCData->pPackedStreamBuffer; + + switch (m_nFileVersion) + { + case 0: + case 3: + { + xnOSMemCopy(&PackedStreamHeader, pPackedBuffer, sizeof(XnPackedStreamFrameHeaderV3)); + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV3); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV3(&PackedStreamHeader, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + case 2: + { + XnPackedStreamFrameHeaderV2* pPackedStreamHeaderV2 = (XnPackedStreamFrameHeaderV2*)pPackedBuffer; + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV2); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV2(pPackedStreamHeaderV2, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + case 1: + { + XnPackedStreamFrameHeaderV1* pPackedStreamHeaderV1 = (XnPackedStreamFrameHeaderV1*)pPackedBuffer; + pPackedBuffer += sizeof(XnPackedStreamFrameHeaderV1); + nRetVal = XnIOAdjustPackedStreamFrameHeaderV1(pPackedStreamHeaderV1, &PackedStreamHeader); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + return XN_STATUS_IO_INVALID_STREAM_HEADER; + } + + // Depth + XnNodeInfo* pNodeInfo; + if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_DEPTH, pNodeInfo)) + { + m_pStreamData->nDataSize = m_pBCData->StreamProperties.nDepthBufferSize; + + nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompDepthBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_DEPTH, FileFrameHeader.FrameProperties.nDepthTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pBCData->StreamProperties.nDepthBufferSize); + XN_IS_STATUS_OK(nRetVal); + + pNodeInfo->nCurrFrameID++; + + pPackedBuffer += PackedStreamHeader.nCompDepthBufferSize; + } + + // Image + if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_IMAGE, pNodeInfo)) + { + m_pStreamData->nDataSize = m_pBCData->StreamProperties.nImageBufferSize; + + nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompImageBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_IMAGE, FileFrameHeader.FrameProperties.nImageTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pBCData->StreamProperties.nImageBufferSize); + XN_IS_STATUS_OK(nRetVal); + + pNodeInfo->nCurrFrameID++; + + pPackedBuffer += PackedStreamHeader.nCompImageBufferSize; + } + + // we do not support MISC + pPackedBuffer += PackedStreamHeader.nCompMiscBufferSize; + + // Audio + if (XN_STATUS_OK == m_nodeInfoMap.Get(XN_STREAM_NAME_AUDIO, pNodeInfo)) + { + m_pStreamData->nDataSize = m_pBCData->StreamProperties.nAudioBufferSize; + + nRetVal = pNodeInfo->pXnCodec->Decompress(pPackedBuffer, PackedStreamHeader.nCompAudioBufferSize, (XnUChar*)m_pStreamData->pData, &m_pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, XN_STREAM_NAME_AUDIO, FileFrameHeader.FrameProperties.nAudioTimeStamp * 1000, m_pBCData->nFramePos, m_pStreamData->pData, m_pStreamData->nDataSize); + XN_IS_STATUS_OK(nRetVal); + + pNodeInfo->nCurrFrameID++; + + pPackedBuffer += PackedStreamHeader.nCompAudioBufferSize; + } + + // Increase the file frame position + m_pBCData->nFramePos++; + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnFileDevice::BCDestroy() +{ + if (m_pBCData != NULL) + { + xnOSFreeAligned(m_pBCData->pPackedStreamBuffer); + xnOSFree(m_pBCData); + } + + return XN_STATUS_OK; +} diff --git a/Source/XnDeviceFile/XnFileOpenNiteImpl.cpp b/Source/XnDeviceFile/XnFileOpenNiteImpl.cpp index a8d1ec6..0c7462c 100644 --- a/Source/XnDeviceFile/XnFileOpenNiteImpl.cpp +++ b/Source/XnDeviceFile/XnFileOpenNiteImpl.cpp @@ -1,39 +1,39 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnExportedFileDevice.h" - -//--------------------------------------------------------------------------- -// Exporting -//--------------------------------------------------------------------------- -XN_EXPORT_MODULE(xn::Module) -XN_EXPORT_PLAYER(XnExportedFileDevice) - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnExportedFileDevice.h" + +//--------------------------------------------------------------------------- +// Exporting +//--------------------------------------------------------------------------- +XN_EXPORT_MODULE(xn::Module) +XN_EXPORT_PLAYER(XnExportedFileDevice) + diff --git a/Source/XnDeviceFile/XnFileWriterStream.cpp b/Source/XnDeviceFile/XnFileWriterStream.cpp index b0686a4..c759dbe 100644 --- a/Source/XnDeviceFile/XnFileWriterStream.cpp +++ b/Source/XnDeviceFile/XnFileWriterStream.cpp @@ -1,70 +1,70 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFileWriterStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFileWriterStream::XnFileWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker) : - XnStreamWriterStream(strType, strName, pDataPacker), - m_nNumFramesPos(0), - m_NumberOfFrames(XN_STREAM_PROPERTY_NUMBER_OF_FRAMES) -{ -} - -XnFileWriterStream::~XnFileWriterStream() -{ -} - -XnStatus XnFileWriterStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_ADD_PROPERTIES(this, &m_NumberOfFrames); - - nRetVal = XnStreamWriterStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFileWriterStream::WriteImpl(XnStreamData* pStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_NumberOfFrames.UnsafeUpdateValue(m_NumberOfFrames.GetValue() + 1); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnStreamWriterStream::WriteImpl(pStreamData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFileWriterStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFileWriterStream::XnFileWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker) : + XnStreamWriterStream(strType, strName, pDataPacker), + m_nNumFramesPos(0), + m_NumberOfFrames(XN_STREAM_PROPERTY_NUMBER_OF_FRAMES) +{ +} + +XnFileWriterStream::~XnFileWriterStream() +{ +} + +XnStatus XnFileWriterStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_ADD_PROPERTIES(this, &m_NumberOfFrames); + + nRetVal = XnStreamWriterStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFileWriterStream::WriteImpl(XnStreamData* pStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_NumberOfFrames.UnsafeUpdateValue(m_NumberOfFrames.GetValue() + 1); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnStreamWriterStream::WriteImpl(pStreamData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceFile/XnFileWriterStream.h b/Source/XnDeviceFile/XnFileWriterStream.h index e03a9d3..47e1c3a 100644 --- a/Source/XnDeviceFile/XnFileWriterStream.h +++ b/Source/XnDeviceFile/XnFileWriterStream.h @@ -1,57 +1,57 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FILE_STREAM_WRITER_H__ -#define __XN_FILE_STREAM_WRITER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnFileWriterStream : public XnStreamWriterStream -{ -public: - XnFileWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker); - ~XnFileWriterStream(); - - XnStatus Init(); - - inline XnUInt64 GetNumberOfFrames() const { return m_NumberOfFrames.GetValue(); } - - XnUInt32 m_nNumFramesPos; - -protected: - XnStatus WriteImpl(XnStreamData* pStreamData); - -private: - XnActualIntProperty m_NumberOfFrames; -}; - -#endif //__XN_FILE_STREAM_WRITER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FILE_STREAM_WRITER_H__ +#define __XN_FILE_STREAM_WRITER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnFileWriterStream : public XnStreamWriterStream +{ +public: + XnFileWriterStream(const XnChar* strType, const XnChar* strName, XnDataPacker* pDataPacker); + ~XnFileWriterStream(); + + XnStatus Init(); + + inline XnUInt64 GetNumberOfFrames() const { return m_NumberOfFrames.GetValue(); } + + XnUInt32 m_nNumFramesPos; + +protected: + XnStatus WriteImpl(XnStreamData* pStreamData); + +private: + XnActualIntProperty m_NumberOfFrames; +}; + +#endif //__XN_FILE_STREAM_WRITER_H__ diff --git a/Source/XnDeviceFile/XnNiInputStream.h b/Source/XnDeviceFile/XnNiInputStream.h index 7ac77dc..31b2c1b 100644 --- a/Source/XnDeviceFile/XnNiInputStream.h +++ b/Source/XnDeviceFile/XnNiInputStream.h @@ -1,84 +1,84 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_XN_INPUT_STREAM_H__ -#define __XN_XN_INPUT_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnInputStream : public XnIOStream -{ -public: - XnInputStream(XnPlayerInputStreamInterface* pStreamInterface, void* pCookie) : - m_pStreamInterface(pStreamInterface), - m_pCookie(pCookie) - {} - - virtual ~XnInputStream() { Free(); } - - XnStatus Init() - { - return m_pStreamInterface->Open(m_pCookie); - } - XnStatus Free() - { - m_pStreamInterface->Close(m_pCookie); - return (XN_STATUS_OK); - } - XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize) - { - return XN_STATUS_NOT_IMPLEMENTED; - } - XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize) - { - XnUInt32 nDummy; - return m_pStreamInterface->Read(m_pCookie, pData, nDataSize, &nDummy); - } - XnStatus Tell(XnUInt32* pnOffset) - { - *pnOffset = m_pStreamInterface->Tell(m_pCookie); - return (XN_STATUS_OK); - } - XnStatus Seek(XnUInt32 nOffset) - { - return m_pStreamInterface->Seek(m_pCookie, XN_OS_SEEK_SET, nOffset); - } - -private: - XnPlayerInputStreamInterface* m_pStreamInterface; - void* m_pCookie; -}; - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_XN_INPUT_STREAM_H__ +#define __XN_XN_INPUT_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnInputStream : public XnIOStream +{ +public: + XnInputStream(XnPlayerInputStreamInterface* pStreamInterface, void* pCookie) : + m_pStreamInterface(pStreamInterface), + m_pCookie(pCookie) + {} + + virtual ~XnInputStream() { Free(); } + + XnStatus Init() + { + return m_pStreamInterface->Open(m_pCookie); + } + XnStatus Free() + { + m_pStreamInterface->Close(m_pCookie); + return (XN_STATUS_OK); + } + XnStatus WriteData(const XnUChar* pData, XnUInt32 nDataSize) + { + return XN_STATUS_NOT_IMPLEMENTED; + } + XnStatus ReadData(XnUChar* pData, XnUInt32 nDataSize) + { + XnUInt32 nDummy; + return m_pStreamInterface->Read(m_pCookie, pData, nDataSize, &nDummy); + } + XnStatus Tell(XnUInt32* pnOffset) + { + *pnOffset = m_pStreamInterface->Tell(m_pCookie); + return (XN_STATUS_OK); + } + XnStatus Seek(XnUInt32 nOffset) + { + return m_pStreamInterface->Seek(m_pCookie, XN_OS_SEEK_SET, nOffset); + } + +private: + XnPlayerInputStreamInterface* m_pStreamInterface; + void* m_pCookie; +}; + + #endif // __XN_XN_INPUT_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/Bayer.cpp b/Source/XnDeviceSensorV2/Bayer.cpp index 7c00cbe..b49099a 100644 --- a/Source/XnDeviceSensorV2/Bayer.cpp +++ b/Source/XnDeviceSensorV2/Bayer.cpp @@ -1,129 +1,129 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "Bayer.h" -#include - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -XnUInt8 Gamma[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -void BayerUpdateGamma(float fGammaCorr) -{ - for(XnUInt32 iG = 0; iG < 256;++iG) - Gamma[iG] = XnUInt32(255*pow(XnDouble(iG)/255.0,(XnDouble)fGammaCorr) + 0.5); -} - -static inline void WriteRGB(XnUInt8 *pBuffer, XnUInt8 nRed, XnUInt8 nGreen, XnUInt8 nBlue) -{ - pBuffer[BAYER_RED] = Gamma[nRed]; - pBuffer[BAYER_GREEN] = Gamma[nGreen]; - pBuffer[BAYER_BLUE] = Gamma[nBlue]; -} - -void Bayer2RGB888(const XnUInt8* pBayerImage, XnUInt8* pRGBImage, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nDownSampleStep, XnUInt32 nBadPixels) -{ - XnUInt8 nRed; - XnUInt8 nGreen; - XnUInt8 nBlue; - const XnUInt8* pBayer; - XnUInt8* pRGB; - - //if (nBadPixels > 1) - //{ - //nBadPixels = 1; - //} - - XnInt32 BAYER_LINE_LENGTH = nXRes; - XnInt32 BAYER_LINE_LENGTH2 = BAYER_LINE_LENGTH*2; - XnInt32 BAYER_RGB_LINE_LENGTH = nXRes*BAYER_BPP; - XnInt32 BAYER_RGB_LINE_LENGTH2 = BAYER_RGB_LINE_LENGTH*2; - - const XnUInt8* pCurrBayer; - XnUInt8* pCurrRGB; - XnUInt32 nColCount; - XnUInt32 nTotalColsCount = (nXRes-2) / 2; - XnUInt32 nTotalRowsCount = (nYRes-4) / 2; - - pBayer = pBayerImage + BAYER_LINE_LENGTH - nBadPixels; - pRGB = pRGBImage + BAYER_RGB_LINE_LENGTH; - - do { - pCurrBayer = pBayer+ 1; - pCurrRGB = pRGB + BAYER_BPP; - - nColCount = nTotalColsCount; - - do { - - nRed = ((XnUInt32)pCurrBayer[-BAYER_LINE_LENGTH]+pCurrBayer[BAYER_LINE_LENGTH]) / 2; - nBlue = ((XnUInt32)pCurrBayer[-1]+pCurrBayer[1]) / 2; - WriteRGB(pCurrRGB+0, nRed, pCurrBayer[0], nBlue); - - nRed = ((XnUInt32)pCurrBayer[-BAYER_LINE_LENGTH+2]+pCurrBayer[BAYER_LINE_LENGTH+2]) / 2; - nGreen = ((XnUInt32)pCurrBayer[0]+pCurrBayer[2]) / 2; - WriteRGB(pCurrRGB+BAYER_BPP, nRed, nGreen, pCurrBayer[1]); - - nGreen = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH-1]+pCurrBayer[BAYER_LINE_LENGTH+1]) / 2; - nBlue = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH2-1]+pCurrBayer[BAYER_LINE_LENGTH2+1]) / 2; - WriteRGB(pCurrRGB+BAYER_RGB_LINE_LENGTH, pCurrBayer[BAYER_LINE_LENGTH], nGreen, nBlue); - - nRed = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH]+pCurrBayer[BAYER_LINE_LENGTH+2]) / 2; - nBlue = ((XnUInt32)pCurrBayer[1]+pCurrBayer[BAYER_LINE_LENGTH2+1]) / 2; - WriteRGB(pCurrRGB+BAYER_RGB_LINE_LENGTH+BAYER_BPP, nRed, pCurrBayer[BAYER_LINE_LENGTH+1], nBlue); - - pCurrBayer += 2; - pCurrRGB += 2*BAYER_BPP; - } while (--nColCount); - - pBayer += BAYER_LINE_LENGTH2; - pRGB += BAYER_RGB_LINE_LENGTH2; - } while (--nTotalRowsCount); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "Bayer.h" +#include + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +XnUInt8 Gamma[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +void BayerUpdateGamma(float fGammaCorr) +{ + for(XnUInt32 iG = 0; iG < 256;++iG) + Gamma[iG] = XnUInt32(255*pow(XnDouble(iG)/255.0,(XnDouble)fGammaCorr) + 0.5); +} + +static inline void WriteRGB(XnUInt8 *pBuffer, XnUInt8 nRed, XnUInt8 nGreen, XnUInt8 nBlue) +{ + pBuffer[BAYER_RED] = Gamma[nRed]; + pBuffer[BAYER_GREEN] = Gamma[nGreen]; + pBuffer[BAYER_BLUE] = Gamma[nBlue]; +} + +void Bayer2RGB888(const XnUInt8* pBayerImage, XnUInt8* pRGBImage, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nDownSampleStep, XnUInt32 nBadPixels) +{ + XnUInt8 nRed; + XnUInt8 nGreen; + XnUInt8 nBlue; + const XnUInt8* pBayer; + XnUInt8* pRGB; + + //if (nBadPixels > 1) + //{ + //nBadPixels = 1; + //} + + XnInt32 BAYER_LINE_LENGTH = nXRes; + XnInt32 BAYER_LINE_LENGTH2 = BAYER_LINE_LENGTH*2; + XnInt32 BAYER_RGB_LINE_LENGTH = nXRes*BAYER_BPP; + XnInt32 BAYER_RGB_LINE_LENGTH2 = BAYER_RGB_LINE_LENGTH*2; + + const XnUInt8* pCurrBayer; + XnUInt8* pCurrRGB; + XnUInt32 nColCount; + XnUInt32 nTotalColsCount = (nXRes-2) / 2; + XnUInt32 nTotalRowsCount = (nYRes-4) / 2; + + pBayer = pBayerImage + BAYER_LINE_LENGTH - nBadPixels; + pRGB = pRGBImage + BAYER_RGB_LINE_LENGTH; + + do { + pCurrBayer = pBayer+ 1; + pCurrRGB = pRGB + BAYER_BPP; + + nColCount = nTotalColsCount; + + do { + + nRed = ((XnUInt32)pCurrBayer[-BAYER_LINE_LENGTH]+pCurrBayer[BAYER_LINE_LENGTH]) / 2; + nBlue = ((XnUInt32)pCurrBayer[-1]+pCurrBayer[1]) / 2; + WriteRGB(pCurrRGB+0, nRed, pCurrBayer[0], nBlue); + + nRed = ((XnUInt32)pCurrBayer[-BAYER_LINE_LENGTH+2]+pCurrBayer[BAYER_LINE_LENGTH+2]) / 2; + nGreen = ((XnUInt32)pCurrBayer[0]+pCurrBayer[2]) / 2; + WriteRGB(pCurrRGB+BAYER_BPP, nRed, nGreen, pCurrBayer[1]); + + nGreen = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH-1]+pCurrBayer[BAYER_LINE_LENGTH+1]) / 2; + nBlue = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH2-1]+pCurrBayer[BAYER_LINE_LENGTH2+1]) / 2; + WriteRGB(pCurrRGB+BAYER_RGB_LINE_LENGTH, pCurrBayer[BAYER_LINE_LENGTH], nGreen, nBlue); + + nRed = ((XnUInt32)pCurrBayer[BAYER_LINE_LENGTH]+pCurrBayer[BAYER_LINE_LENGTH+2]) / 2; + nBlue = ((XnUInt32)pCurrBayer[1]+pCurrBayer[BAYER_LINE_LENGTH2+1]) / 2; + WriteRGB(pCurrRGB+BAYER_RGB_LINE_LENGTH+BAYER_BPP, nRed, pCurrBayer[BAYER_LINE_LENGTH+1], nBlue); + + pCurrBayer += 2; + pCurrRGB += 2*BAYER_BPP; + } while (--nColCount); + + pBayer += BAYER_LINE_LENGTH2; + pRGB += BAYER_RGB_LINE_LENGTH2; + } while (--nTotalRowsCount); +} diff --git a/Source/XnDeviceSensorV2/Bayer.h b/Source/XnDeviceSensorV2/Bayer.h index 15c3925..4175690 100644 --- a/Source/XnDeviceSensorV2/Bayer.h +++ b/Source/XnDeviceSensorV2/Bayer.h @@ -1,50 +1,50 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_BAYER_H_ -#define _XN_BAYER_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define BAYER_RED 0 -#define BAYER_GREEN 1 -#define BAYER_BLUE 2 -#define BAYER_BPP 3 - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -void BayerUpdateGamma(float fGammaCorr); -void Bayer2RGB888(const XnUInt8* pBayerImage, XnUInt8* pRGBImage, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nDownSampleStep, XnUInt32 nBadPixels); - -#endif //_XN_BAYER_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_BAYER_H_ +#define _XN_BAYER_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define BAYER_RED 0 +#define BAYER_GREEN 1 +#define BAYER_BLUE 2 +#define BAYER_BPP 3 + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +void BayerUpdateGamma(float fGammaCorr); +void Bayer2RGB888(const XnUInt8* pBayerImage, XnUInt8* pRGBImage, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nDownSampleStep, XnUInt32 nBadPixels); + +#endif //_XN_BAYER_H_ diff --git a/Source/XnDeviceSensorV2/CMakeLists.txt b/Source/XnDeviceSensorV2/CMakeLists.txt new file mode 100644 index 0000000..229c89b --- /dev/null +++ b/Source/XnDeviceSensorV2/CMakeLists.txt @@ -0,0 +1,47 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR} + ${XNCORE_INCLUDE_DIR} + ${LIBJPEG_INCLUDE_DIR} + ../ +) + +# Get sources +# ------------ +file(GLOB ${XNDEVICESENSOR_LIB_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_library( + ${XNDEVICESENSOR_LIB_NAME} + SHARED + ${${XNDEVICESENSOR_LIB_NAME}_sources} +) + +target_link_libraries( + ${XNDEVICESENSOR_LIB_NAME} + ${XNFORMAT_LIB_NAME} + ${XNDDK_LIB_NAME} +) + +# The install_name is Mac OSX specific and is used to set the RPATH on a executable +# On Mac OSX the library can hold information for the rpath of the executable which +# uses the library. +# ---------------------------------------------------------------------------------- +if(SENSOR_PLATFORM_MAC) + set_target_properties(${XNDEVICESENSOR_LIB_NAME} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR ${INSTALL_NAME_VALUE} + ) +endif() + + + +# Set install dir +# --------------- +install( + TARGETS ${XNDEVICESENSOR_LIB_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) + diff --git a/Source/XnDeviceSensorV2/IXnSensorStream.h b/Source/XnDeviceSensorV2/IXnSensorStream.h index c4fde67..aa3a189 100644 --- a/Source/XnDeviceSensorV2/IXnSensorStream.h +++ b/Source/XnDeviceSensorV2/IXnSensorStream.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __I_XN_SENSOR_STREAM_H__ -#define __I_XN_SENSOR_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// Forward Declarations -//--------------------------------------------------------------------------- -class XnDataProcessor; - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class IXnSensorStream -{ -public: - ~IXnSensorStream() {} - - virtual void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) = 0; - virtual XnStatus ConfigureStreamImpl() = 0; - virtual XnStatus OpenStreamImpl() = 0; - virtual XnStatus CloseStreamImpl() = 0; - virtual XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor) = 0; - virtual XnStatus MapPropertiesToFirmware() = 0; - virtual XnSharedMemoryBufferPool* GetSharedMemoryBuffer() = 0; -}; - -#endif //__I_XN_SENSOR_STREAM_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __I_XN_SENSOR_STREAM_H__ +#define __I_XN_SENSOR_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// Forward Declarations +//--------------------------------------------------------------------------- +class XnDataProcessor; + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class IXnSensorStream +{ +public: + ~IXnSensorStream() {} + + virtual void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) = 0; + virtual XnStatus ConfigureStreamImpl() = 0; + virtual XnStatus OpenStreamImpl() = 0; + virtual XnStatus CloseStreamImpl() = 0; + virtual XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor) = 0; + virtual XnStatus MapPropertiesToFirmware() = 0; + virtual XnSharedMemoryBufferPool* GetSharedMemoryBuffer() = 0; +}; + +#endif //__I_XN_SENSOR_STREAM_H__ diff --git a/Source/XnDeviceSensorV2/Registration.cpp b/Source/XnDeviceSensorV2/Registration.cpp index 3a033a2..be29333 100644 --- a/Source/XnDeviceSensorV2/Registration.cpp +++ b/Source/XnDeviceSensorV2/Registration.cpp @@ -1,581 +1,581 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "Registration.h" -#include "XnSensorDepthStream.h" -#include "XnSensor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnRegistration::XnRegistration() : - m_pRegistrationTable(NULL), - m_pDepthToShiftTable(NULL), - m_pDevicePrivateData(NULL), - m_pDepthStream(NULL), - m_bInitialized(FALSE), - m_pTempBuffer(NULL), - m_bD2SAlloc(FALSE) -{ - -} - -inline XnDouble XnRegistrationFunction1000(XnDouble a, XnDouble b, XnDouble c, XnDouble d, XnDouble e, XnDouble f, XnInt16 x, XnInt16 y) -{ - return a*x*x + b*y*y + c*x*y + d*x + e*y + f; -} - -inline XnDouble XnXRegistrationFunction1000(XnRegistrationInformation1000& regInfo1000, XnUInt16 nX, XnUInt16 nY, XnUInt32 nXRes, XnUInt32 nYRes) -{ - return XnRegistrationFunction1000( - regInfo1000.FuncX.dA, - regInfo1000.FuncX.dB, - regInfo1000.FuncX.dC, - regInfo1000.FuncX.dD, - regInfo1000.FuncX.dE, - regInfo1000.FuncX.dF, - nX - nXRes/2, - nY - nYRes/2); -} - -inline XnDouble XnYRegistrationFunction1000(XnRegistrationInformation1000& regInfo1000, XnUInt16 nX, XnUInt16 nY, XnUInt32 nXRes, XnUInt32 nYRes) -{ - return XnRegistrationFunction1000( - regInfo1000.FuncY.dA, - regInfo1000.FuncY.dB, - regInfo1000.FuncY.dC, - regInfo1000.FuncY.dD, - regInfo1000.FuncY.dE, - regInfo1000.FuncY.dF, - nX - nXRes/2, - nY - nYRes/2); -} - -XnStatus XnRegistration::BuildRegTable1000() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // take needed parameters to perform registration - XnRegistrationInformation1000 regInfo1000; - nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION, ®Info1000, sizeof(regInfo1000), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); - XN_IS_STATUS_OK(nRetVal); - - XnUInt16* pRegTable = m_pRegistrationTable; - XnDouble dDeltaX, dDeltaY; - - XnDouble dNewX = 0, - dNewY = 0; - - XnUInt64 nDepthXRes = m_pDepthStream->GetXRes(); - XnUInt64 nDepthYRes = m_pDepthStream->GetYRes(); - - const XnUInt16 nIllegalValue = XnUInt16(nDepthXRes*4); - - for (XnUInt16 nY = 0; nY < nDepthYRes; nY++) - { - for (XnUInt16 nX = 0; nX < nDepthXRes; nX++) - { - dDeltaX = XnXRegistrationFunction1000(regInfo1000, nX, nY, nDepthXRes, nDepthYRes); - dDeltaY = XnYRegistrationFunction1000(regInfo1000, nX, nY, nDepthXRes, nDepthYRes); - - dNewX = (nX + dDeltaX); - dNewY = nY + dDeltaY; - - if (dNewY < 1 || dNewY > nDepthYRes) - { - dNewY = 1; - dNewX = nIllegalValue; - } - if (dNewX < 1 || dNewX > nDepthXRes) - { - dNewX = nIllegalValue; - } - - dNewX *= XN_REG_X_SCALE; - - *pRegTable = (XnUInt16)dNewX; - *(pRegTable + 1) = (XnUInt16)dNewY; - - pRegTable += 2; - } - } - - m_dShiftFactor = regInfo1000.dBeta; - - return (XN_STATUS_OK); - -} - -static void incrementalFitting50(XnInt64 dPrev, XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt32 betaPrev, XnInt32 dBeta, XnInt64 &dCurr, XnInt64 &ddCurr, XnInt64 &dddCurr, XnInt32 &betaCurr); -static void incrementalFitting50(XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt64 &ddCurr, XnInt64 &dddCurr) { XnInt64 dummy1; XnInt32 dummy2; incrementalFitting50(0, ddPrev, dddPrev, coeff, 0, 0, dummy1, ddCurr, dddCurr, dummy2); } -static void incrementalFitting50(XnInt64 dddPrev, XnInt64 coeff, XnInt64 &dddCurr) { XnInt64 dummy1, dummy2; XnInt32 dummy3; incrementalFitting50(0, 0, dddPrev, coeff, 0, 0, dummy1, dummy2, dddCurr, dummy3); } -void incrementalFitting50(XnInt64 dPrev, XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt32 betaPrev, XnInt32 dBeta, XnInt64 &dCurr, XnInt64 &ddCurr, XnInt64 &dddCurr, XnInt32 &betaCurr) -{ - dCurr = dPrev+(ddPrev>>6); - ddCurr = ddPrev+(dddPrev>>8); - dddCurr = dddPrev+coeff; - betaCurr = betaPrev+dBeta; -} - -XnInt32 GetFieldValueSigned(XnUInt32 regValue, XnInt32 fieldWidth, XnInt32 fieldOffset) -{ - XnInt32 val = (int)(regValue>>fieldOffset); - val = (val<<(32-fieldWidth))>>(32-fieldWidth); - return val; -} - -void CreateDXDYTablesInternal(XnDouble* RegXTable, XnDouble* RegYTable, - XnInt32 resX, XnInt32 resY, - XnInt64 AX6, XnInt64 BX6, XnInt64 CX2, XnInt64 DX2, - XnInt32 deltaBetaX, - XnInt64 AY6, XnInt64 BY6, XnInt64 CY2, XnInt64 DY2, - XnInt32 deltaBetaY, - XnInt64 dX0, XnInt64 dY0, - XnInt64 dXdX0, XnInt64 dXdY0, XnInt64 dYdX0, XnInt64 dYdY0, - XnInt64 dXdXdX0, XnInt64 dYdXdX0, XnInt64 dYdXdY0, XnInt64 dXdXdY0, - XnInt64 dYdYdX0, XnInt64 dYdYdY0, - XnInt32 betaX, XnInt32 betaY) -{ - XnInt32 tOffs = 0; - - for(XnInt32 row = 0 ; rowGetDeviceMaxDepth(); - - XnDouble dPlanePixelSize; - m_pStream->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &dPlanePixelSize); - - XnUInt64 nPlaneDsr; - XnDouble dPlaneDsr; - m_pStream->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nPlaneDsr); - dPlaneDsr = nPlaneDsr; - - XnDouble dPelSize = 1.0 / (dPlanePixelSize * nXScale * S2D_PEL_CONST); - XnDouble dPelDCC = XN_SENSOR_DEPTH_RGB_CMOS_DISTANCE * dPelSize * S2D_PEL_CONST; - XnDouble dPelDSR = dPlaneDsr * dPelSize * S2D_PEL_CONST; - - memset(pRGBRegDepthToShiftTable, XN_DEVICE_SENSOR_NO_DEPTH_VALUE, nMaxDepth * sizeof(XnInt16)); - - for (nIndex = 0; nIndex < nMaxDepth; nIndex++) - { - dDepth = nIndex * dPelSize; - pRGBRegDepthToShiftTable[nIndex] = ((dPelDCC * (dDepth - dPelDSR) / dDepth) + (S2D_CONST_OFFSET)) * RGB_REG_X_VAL_SCALE; - } -} - -XnStatus XnRegistration::BuildRegTable1080() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // take needed parameters to perform registration - XnRegistrationInformation1080 RegData; - nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION, &RegData, sizeof(RegData), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); - XN_IS_STATUS_OK(nRetVal); - - xnOSMemSet(&m_padInfo, 0, sizeof(m_padInfo)); - nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_PADDING, &m_padInfo, sizeof(m_padInfo), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_ALIGNED_CALLOC(m_pDepthToShiftTable, XnUInt16, m_pDepthStream->GetXRes()*m_pDepthStream->GetYRes(), XN_DEFAULT_MEM_ALIGN); - m_bD2SAlloc = TRUE; - - BuildDepthToShiftTable(m_pDepthToShiftTable, m_pDepthStream); - - XnDouble* RegXTable = XN_NEW_ARR(XnDouble, RGB_REG_X_RES*RGB_REG_Y_RES); - XnDouble* RegYTable = XN_NEW_ARR(XnDouble, RGB_REG_X_RES*RGB_REG_Y_RES); - - XnInt16* pRGBRegDepthToShiftTable = (XnInt16*)m_pDepthToShiftTable; - XnUInt16 nDepthXRes = XN_DEPTH_XRES; - XnUInt16 nDepthYRes = XN_DEPTH_YRES; - XnUInt32 nXScale = XN_CMOS_VGAOUTPUT_XRES / XN_DEPTH_XRES; - XnDouble* pRegXTable = (XnDouble*)RegXTable; - XnDouble* pRegYTable = (XnDouble*)RegYTable; - XnInt16* pRegTable = (XnInt16*)m_pRegistrationTable; - XnDouble nNewX = 0; - XnDouble nNewY = 0; - - // Create the dx dy tables - CreateDXDYTables(RegXTable, RegYTable, - nDepthXRes, nDepthYRes, - GetFieldValueSigned(RegData.nRGS_AX, 32, 0), - GetFieldValueSigned(RegData.nRGS_BX, 32, 0), - GetFieldValueSigned(RegData.nRGS_CX, 32, 0), - GetFieldValueSigned(RegData.nRGS_DX, 32, 0), - GetFieldValueSigned(RegData.nRGS_DX_BETA_INC, 24, 0), - GetFieldValueSigned(RegData.nRGS_AY, 32, 0), - GetFieldValueSigned(RegData.nRGS_BY, 32, 0), - GetFieldValueSigned(RegData.nRGS_CY, 32, 0), - GetFieldValueSigned(RegData.nRGS_DY, 32, 0), - GetFieldValueSigned(RegData.nRGS_DY_BETA_INC, 24, 0), - GetFieldValueSigned(RegData.nRGS_DX_START, 19, 0), - GetFieldValueSigned(RegData.nRGS_DY_START, 19, 0), - GetFieldValueSigned(RegData.nRGS_DXDX_START, 21, 0), - GetFieldValueSigned(RegData.nRGS_DXDY_START, 21, 0), - GetFieldValueSigned(RegData.nRGS_DYDX_START, 21, 0), - GetFieldValueSigned(RegData.nRGS_DYDY_START, 21, 0), - GetFieldValueSigned(RegData.nRGS_DXDXDX_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DYDXDX_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DYDXDY_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DXDXDY_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DYDYDX_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DYDYDY_START, 27, 0), - GetFieldValueSigned(RegData.nRGS_DX_BETA_START, 17, 0), - GetFieldValueSigned(RegData.nRGS_DY_BETA_START, 17, 0) - ); - - // Pre-process the table, do sanity checks and convert it from double to ints (for better performance) - for (XnInt32 nY=0; nY nDepthYRes) - { - nNewY = nDepthYRes; - goto FinishLoop; - } - - *pRegTable = nNewX; - *(pRegTable+1) = nNewY; - - pRegXTable++; - pRegYTable++; - pRegTable+=2; - } - } - -FinishLoop: - XN_DELETE_ARR(RegXTable); - XN_DELETE_ARR(RegYTable); - - return (XN_STATUS_OK); -} - -XnStatus XnRegistration::BuildRegTable() -{ - XnStatus nRetVal = XN_STATUS_OK; - - m_b1000 = (m_pDevicePrivateData->ChipInfo.nChipVer == XN_SENSOR_CHIP_VER_PS1000); - if (m_b1000) - { - return BuildRegTable1000(); - } - else - { - return BuildRegTable1080(); - } - - return (XN_STATUS_OK); -} - -XnStatus XnRegistration::Init(XnDevicePrivateData* pDevicePrivateData, XnSensorDepthStream* pDepthStream, XnUInt16* pDepthToShiftTable) -{ - XnStatus nRetVal = XN_STATUS_OK; - - Free(); - - m_pDevicePrivateData = pDevicePrivateData; - m_pDepthStream = pDepthStream; - m_pDepthToShiftTable = pDepthToShiftTable; - - // allocate table - XN_VALIDATE_ALIGNED_CALLOC(m_pRegistrationTable, XnUInt16, pDepthStream->GetXRes()*pDepthStream->GetYRes()*2, XN_DEFAULT_MEM_ALIGN); - - // allocate temp buffer - XN_VALIDATE_ALIGNED_CALLOC(m_pTempBuffer, XnDepthPixel, pDepthStream->GetXRes()*pDepthStream->GetYRes(), XN_DEFAULT_MEM_ALIGN); - - nRetVal = BuildRegTable(); - XN_IS_STATUS_OK(nRetVal); - - m_bInitialized = TRUE; - - return XN_STATUS_OK; -} - -XnStatus XnRegistration::Free() -{ - m_bInitialized = FALSE; - - if (m_pRegistrationTable != NULL) - { - xnOSFreeAligned(m_pRegistrationTable); - m_pRegistrationTable = NULL; - } - - if (m_pTempBuffer != NULL) - { - xnOSFreeAligned(m_pTempBuffer); - m_pTempBuffer = NULL; - } - - if (m_bD2SAlloc && m_pDepthToShiftTable != NULL) - { - xnOSFreeAligned(m_pDepthToShiftTable); - m_pDepthToShiftTable = NULL; - m_bD2SAlloc = FALSE; - } - - return (XN_STATUS_OK); -} - -void XnRegistration::Apply(XnDepthPixel* pDM) -{ - XnUInt32 nDepthXRes = m_pDepthStream->GetXRes(); - XnUInt32 nDepthYRes = m_pDepthStream->GetYRes(); - - // copy buffer aside - xnOSMemCopy(m_pTempBuffer, pDM, nDepthXRes*nDepthYRes*sizeof(XnDepthPixel)); - - if (m_b1000) - { - Apply1000(m_pTempBuffer, pDM); - } - else - { - Apply1080(m_pTempBuffer, pDM); - } -} - -void XnRegistration::Apply1000(XnDepthPixel* pInput, XnDepthPixel* pOutput) -{ - XnUInt32 nDepthXRes = m_pDepthStream->GetXRes(); - XnUInt32 nDepthYRes = m_pDepthStream->GetYRes(); - - XnUInt16* pRegTable = m_pRegistrationTable; - XnUInt16* pDepth2ShiftTable = m_pDepthToShiftTable; - XnDepthPixel* pInputEnd = pInput + nDepthYRes*nDepthXRes; - XnDepthPixel nValue, nOutValue; - XnInt32 nNewX, nNewY; - XnUInt32 nArrPos; - - xnOSMemSet(pOutput, 0, m_pDepthStream->GetRequiredDataSize()); - - XnDouble dShiftFactor = m_dShiftFactor; - XnUInt32 nConstShift = m_pDepthStream->GetConstShift(); - - while (pInput != pInputEnd) - { - nValue = *pInput; - - if (nValue != 0) - { - nNewX = (XnInt32)(XnDouble(*pRegTable)/XN_REG_X_SCALE + XnInt32(pDepth2ShiftTable[nValue]/XN_REG_PARAB_COEFF - nConstShift) * dShiftFactor); - nNewY = *(pRegTable+1); - - if ( nNewX < nDepthXRes && nNewY < nDepthYRes ) - { - nArrPos = nNewY * nDepthXRes + nNewX; - nOutValue = pOutput[nArrPos]; - - if (nOutValue == 0 || nOutValue > nValue) - { - if ( nNewX > 0 && nNewY > 0 ) - { - pOutput[nArrPos-nDepthXRes] = nValue; - pOutput[nArrPos-nDepthXRes-1] = nValue; - pOutput[nArrPos-1] = nValue; - } - else if( nNewY > 0 ) - { - pOutput[nArrPos-nDepthXRes] = nValue; - } - else if( nNewX > 0 ) - { - pOutput[nArrPos-1] = nValue; - } - - pOutput[nArrPos] = nValue; - } - } - } - - pInput++; - pRegTable += 2; - } -} - -void XnRegistration::Apply1080(XnDepthPixel* pInput, XnDepthPixel* pOutput) -{ - XnInt16* pRegTable = (XnInt16*)m_pRegistrationTable; - XnInt16* pRGBRegDepthToShiftTable = (XnInt16*)m_pDepthToShiftTable; - XnDepthPixel nValue = 0; - XnDepthPixel nOutValue = 0; - XnUInt32 nNewX = 0; - XnUInt32 nNewY = 0; - XnUInt32 nArrPos = 0; - XnUInt32 nDepthXRes = XN_DEPTH_XRES; - XnUInt32 nDepthYRes = XN_DEPTH_YRES; - - memset(pOutput, XN_DEVICE_SENSOR_NO_DEPTH_VALUE, nDepthXRes*nDepthYRes*sizeof(XnDepthPixel)); - - // entire map should be shifted by X lines - XnUInt32 nConstOffset = nDepthYRes*m_padInfo.nStartLines; - - XnDepthPixel* pInputEnd = pInput + nDepthYRes*nDepthXRes; - - XnBool bMirror = m_pDepthStream->IsMirrored(); - - for (XnUInt32 y = 0; y < nDepthYRes; ++y) - { - pRegTable = (XnInt16*)&m_pRegistrationTable[ bMirror ? (y+1) * nDepthXRes * 2 - 2 : y * nDepthXRes * 2 ]; - for (XnUInt32 x = 0; x < nDepthXRes; ++x) - { - nValue = *pInput; - - if (nValue != XN_DEVICE_SENSOR_NO_DEPTH_VALUE) - { - nNewX = (XnUInt32)(*pRegTable + pRGBRegDepthToShiftTable[nValue]) / RGB_REG_X_VAL_SCALE; - nNewY = *(pRegTable+1); - - if (nNewX < nDepthXRes && nNewY < nDepthYRes ) - { - nArrPos = bMirror ? (nNewY+1)*nDepthXRes - nNewX - 2 : (nNewY*nDepthXRes) + nNewX; - nArrPos -= nConstOffset; - - nOutValue = pOutput[nArrPos]; - - if ((nOutValue == XN_DEVICE_SENSOR_NO_DEPTH_VALUE) || (nOutValue > nValue)) - { - if ( nNewX > 0 && nNewY > 0 ) - { - pOutput[nArrPos-nDepthXRes] = nValue; - pOutput[nArrPos-nDepthXRes-1] = nValue; - pOutput[nArrPos-1] = nValue; - } - else if( nNewY > 0 ) - { - pOutput[nArrPos-nDepthXRes] = nValue; - } - else if( nNewX > 0 ) - { - pOutput[nArrPos-1] = nValue; - } - - pOutput[nArrPos] = nValue; - } - } - } - - pInput++; - bMirror ? pRegTable-=2 : pRegTable+=2; - } - } -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "Registration.h" +#include "XnSensorDepthStream.h" +#include "XnSensor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnRegistration::XnRegistration() : + m_pRegistrationTable(NULL), + m_pDepthToShiftTable(NULL), + m_pDevicePrivateData(NULL), + m_pDepthStream(NULL), + m_bInitialized(FALSE), + m_pTempBuffer(NULL), + m_bD2SAlloc(FALSE) +{ + +} + +inline XnDouble XnRegistrationFunction1000(XnDouble a, XnDouble b, XnDouble c, XnDouble d, XnDouble e, XnDouble f, XnInt16 x, XnInt16 y) +{ + return a*x*x + b*y*y + c*x*y + d*x + e*y + f; +} + +inline XnDouble XnXRegistrationFunction1000(XnRegistrationInformation1000& regInfo1000, XnUInt16 nX, XnUInt16 nY, XnUInt32 nXRes, XnUInt32 nYRes) +{ + return XnRegistrationFunction1000( + regInfo1000.FuncX.dA, + regInfo1000.FuncX.dB, + regInfo1000.FuncX.dC, + regInfo1000.FuncX.dD, + regInfo1000.FuncX.dE, + regInfo1000.FuncX.dF, + nX - nXRes/2, + nY - nYRes/2); +} + +inline XnDouble XnYRegistrationFunction1000(XnRegistrationInformation1000& regInfo1000, XnUInt16 nX, XnUInt16 nY, XnUInt32 nXRes, XnUInt32 nYRes) +{ + return XnRegistrationFunction1000( + regInfo1000.FuncY.dA, + regInfo1000.FuncY.dB, + regInfo1000.FuncY.dC, + regInfo1000.FuncY.dD, + regInfo1000.FuncY.dE, + regInfo1000.FuncY.dF, + nX - nXRes/2, + nY - nYRes/2); +} + +XnStatus XnRegistration::BuildRegTable1000() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // take needed parameters to perform registration + XnRegistrationInformation1000 regInfo1000; + nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION, ®Info1000, sizeof(regInfo1000), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); + XN_IS_STATUS_OK(nRetVal); + + XnUInt16* pRegTable = m_pRegistrationTable; + XnDouble dDeltaX, dDeltaY; + + XnDouble dNewX = 0, + dNewY = 0; + + XnUInt64 nDepthXRes = m_pDepthStream->GetXRes(); + XnUInt64 nDepthYRes = m_pDepthStream->GetYRes(); + + const XnUInt16 nIllegalValue = XnUInt16(nDepthXRes*4); + + for (XnUInt16 nY = 0; nY < nDepthYRes; nY++) + { + for (XnUInt16 nX = 0; nX < nDepthXRes; nX++) + { + dDeltaX = XnXRegistrationFunction1000(regInfo1000, nX, nY, nDepthXRes, nDepthYRes); + dDeltaY = XnYRegistrationFunction1000(regInfo1000, nX, nY, nDepthXRes, nDepthYRes); + + dNewX = (nX + dDeltaX); + dNewY = nY + dDeltaY; + + if (dNewY < 1 || dNewY > nDepthYRes) + { + dNewY = 1; + dNewX = nIllegalValue; + } + if (dNewX < 1 || dNewX > nDepthXRes) + { + dNewX = nIllegalValue; + } + + dNewX *= XN_REG_X_SCALE; + + *pRegTable = (XnUInt16)dNewX; + *(pRegTable + 1) = (XnUInt16)dNewY; + + pRegTable += 2; + } + } + + m_dShiftFactor = regInfo1000.dBeta; + + return (XN_STATUS_OK); + +} + +static void incrementalFitting50(XnInt64 dPrev, XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt32 betaPrev, XnInt32 dBeta, XnInt64 &dCurr, XnInt64 &ddCurr, XnInt64 &dddCurr, XnInt32 &betaCurr); +static void incrementalFitting50(XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt64 &ddCurr, XnInt64 &dddCurr) { XnInt64 dummy1; XnInt32 dummy2; incrementalFitting50(0, ddPrev, dddPrev, coeff, 0, 0, dummy1, ddCurr, dddCurr, dummy2); } +static void incrementalFitting50(XnInt64 dddPrev, XnInt64 coeff, XnInt64 &dddCurr) { XnInt64 dummy1, dummy2; XnInt32 dummy3; incrementalFitting50(0, 0, dddPrev, coeff, 0, 0, dummy1, dummy2, dddCurr, dummy3); } +void incrementalFitting50(XnInt64 dPrev, XnInt64 ddPrev, XnInt64 dddPrev, XnInt64 coeff, XnInt32 betaPrev, XnInt32 dBeta, XnInt64 &dCurr, XnInt64 &ddCurr, XnInt64 &dddCurr, XnInt32 &betaCurr) +{ + dCurr = dPrev+(ddPrev>>6); + ddCurr = ddPrev+(dddPrev>>8); + dddCurr = dddPrev+coeff; + betaCurr = betaPrev+dBeta; +} + +XnInt32 GetFieldValueSigned(XnUInt32 regValue, XnInt32 fieldWidth, XnInt32 fieldOffset) +{ + XnInt32 val = (int)(regValue>>fieldOffset); + val = (val<<(32-fieldWidth))>>(32-fieldWidth); + return val; +} + +void CreateDXDYTablesInternal(XnDouble* RegXTable, XnDouble* RegYTable, + XnInt32 resX, XnInt32 resY, + XnInt64 AX6, XnInt64 BX6, XnInt64 CX2, XnInt64 DX2, + XnInt32 deltaBetaX, + XnInt64 AY6, XnInt64 BY6, XnInt64 CY2, XnInt64 DY2, + XnInt32 deltaBetaY, + XnInt64 dX0, XnInt64 dY0, + XnInt64 dXdX0, XnInt64 dXdY0, XnInt64 dYdX0, XnInt64 dYdY0, + XnInt64 dXdXdX0, XnInt64 dYdXdX0, XnInt64 dYdXdY0, XnInt64 dXdXdY0, + XnInt64 dYdYdX0, XnInt64 dYdYdY0, + XnInt32 betaX, XnInt32 betaY) +{ + XnInt32 tOffs = 0; + + for(XnInt32 row = 0 ; rowGetDeviceMaxDepth(); + + XnDouble dPlanePixelSize; + m_pStream->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &dPlanePixelSize); + + XnUInt64 nPlaneDsr; + XnDouble dPlaneDsr; + m_pStream->GetProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &nPlaneDsr); + dPlaneDsr = nPlaneDsr; + + XnDouble dPelSize = 1.0 / (dPlanePixelSize * nXScale * S2D_PEL_CONST); + XnDouble dPelDCC = XN_SENSOR_DEPTH_RGB_CMOS_DISTANCE * dPelSize * S2D_PEL_CONST; + XnDouble dPelDSR = dPlaneDsr * dPelSize * S2D_PEL_CONST; + + memset(pRGBRegDepthToShiftTable, XN_DEVICE_SENSOR_NO_DEPTH_VALUE, nMaxDepth * sizeof(XnInt16)); + + for (nIndex = 0; nIndex < nMaxDepth; nIndex++) + { + dDepth = nIndex * dPelSize; + pRGBRegDepthToShiftTable[nIndex] = ((dPelDCC * (dDepth - dPelDSR) / dDepth) + (S2D_CONST_OFFSET)) * RGB_REG_X_VAL_SCALE; + } +} + +XnStatus XnRegistration::BuildRegTable1080() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // take needed parameters to perform registration + XnRegistrationInformation1080 RegData; + nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION, &RegData, sizeof(RegData), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); + XN_IS_STATUS_OK(nRetVal); + + xnOSMemSet(&m_padInfo, 0, sizeof(m_padInfo)); + nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_PADDING, &m_padInfo, sizeof(m_padInfo), m_pDepthStream->GetResolution(), m_pDepthStream->GetFPS()); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_ALIGNED_CALLOC(m_pDepthToShiftTable, XnUInt16, m_pDepthStream->GetXRes()*m_pDepthStream->GetYRes(), XN_DEFAULT_MEM_ALIGN); + m_bD2SAlloc = TRUE; + + BuildDepthToShiftTable(m_pDepthToShiftTable, m_pDepthStream); + + XnDouble* RegXTable = XN_NEW_ARR(XnDouble, RGB_REG_X_RES*RGB_REG_Y_RES); + XnDouble* RegYTable = XN_NEW_ARR(XnDouble, RGB_REG_X_RES*RGB_REG_Y_RES); + + XnInt16* pRGBRegDepthToShiftTable = (XnInt16*)m_pDepthToShiftTable; + XnUInt16 nDepthXRes = XN_DEPTH_XRES; + XnUInt16 nDepthYRes = XN_DEPTH_YRES; + XnUInt32 nXScale = XN_CMOS_VGAOUTPUT_XRES / XN_DEPTH_XRES; + XnDouble* pRegXTable = (XnDouble*)RegXTable; + XnDouble* pRegYTable = (XnDouble*)RegYTable; + XnInt16* pRegTable = (XnInt16*)m_pRegistrationTable; + XnDouble nNewX = 0; + XnDouble nNewY = 0; + + // Create the dx dy tables + CreateDXDYTables(RegXTable, RegYTable, + nDepthXRes, nDepthYRes, + GetFieldValueSigned(RegData.nRGS_AX, 32, 0), + GetFieldValueSigned(RegData.nRGS_BX, 32, 0), + GetFieldValueSigned(RegData.nRGS_CX, 32, 0), + GetFieldValueSigned(RegData.nRGS_DX, 32, 0), + GetFieldValueSigned(RegData.nRGS_DX_BETA_INC, 24, 0), + GetFieldValueSigned(RegData.nRGS_AY, 32, 0), + GetFieldValueSigned(RegData.nRGS_BY, 32, 0), + GetFieldValueSigned(RegData.nRGS_CY, 32, 0), + GetFieldValueSigned(RegData.nRGS_DY, 32, 0), + GetFieldValueSigned(RegData.nRGS_DY_BETA_INC, 24, 0), + GetFieldValueSigned(RegData.nRGS_DX_START, 19, 0), + GetFieldValueSigned(RegData.nRGS_DY_START, 19, 0), + GetFieldValueSigned(RegData.nRGS_DXDX_START, 21, 0), + GetFieldValueSigned(RegData.nRGS_DXDY_START, 21, 0), + GetFieldValueSigned(RegData.nRGS_DYDX_START, 21, 0), + GetFieldValueSigned(RegData.nRGS_DYDY_START, 21, 0), + GetFieldValueSigned(RegData.nRGS_DXDXDX_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DYDXDX_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DYDXDY_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DXDXDY_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DYDYDX_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DYDYDY_START, 27, 0), + GetFieldValueSigned(RegData.nRGS_DX_BETA_START, 17, 0), + GetFieldValueSigned(RegData.nRGS_DY_BETA_START, 17, 0) + ); + + // Pre-process the table, do sanity checks and convert it from double to ints (for better performance) + for (XnInt32 nY=0; nY nDepthYRes) + { + nNewY = nDepthYRes; + goto FinishLoop; + } + + *pRegTable = nNewX; + *(pRegTable+1) = nNewY; + + pRegXTable++; + pRegYTable++; + pRegTable+=2; + } + } + +FinishLoop: + XN_DELETE_ARR(RegXTable); + XN_DELETE_ARR(RegYTable); + + return (XN_STATUS_OK); +} + +XnStatus XnRegistration::BuildRegTable() +{ + XnStatus nRetVal = XN_STATUS_OK; + + m_b1000 = (m_pDevicePrivateData->ChipInfo.nChipVer == XN_SENSOR_CHIP_VER_PS1000); + if (m_b1000) + { + return BuildRegTable1000(); + } + else + { + return BuildRegTable1080(); + } + + return (XN_STATUS_OK); +} + +XnStatus XnRegistration::Init(XnDevicePrivateData* pDevicePrivateData, XnSensorDepthStream* pDepthStream, XnUInt16* pDepthToShiftTable) +{ + XnStatus nRetVal = XN_STATUS_OK; + + Free(); + + m_pDevicePrivateData = pDevicePrivateData; + m_pDepthStream = pDepthStream; + m_pDepthToShiftTable = pDepthToShiftTable; + + // allocate table + XN_VALIDATE_ALIGNED_CALLOC(m_pRegistrationTable, XnUInt16, pDepthStream->GetXRes()*pDepthStream->GetYRes()*2, XN_DEFAULT_MEM_ALIGN); + + // allocate temp buffer + XN_VALIDATE_ALIGNED_CALLOC(m_pTempBuffer, XnDepthPixel, pDepthStream->GetXRes()*pDepthStream->GetYRes(), XN_DEFAULT_MEM_ALIGN); + + nRetVal = BuildRegTable(); + XN_IS_STATUS_OK(nRetVal); + + m_bInitialized = TRUE; + + return XN_STATUS_OK; +} + +XnStatus XnRegistration::Free() +{ + m_bInitialized = FALSE; + + if (m_pRegistrationTable != NULL) + { + xnOSFreeAligned(m_pRegistrationTable); + m_pRegistrationTable = NULL; + } + + if (m_pTempBuffer != NULL) + { + xnOSFreeAligned(m_pTempBuffer); + m_pTempBuffer = NULL; + } + + if (m_bD2SAlloc && m_pDepthToShiftTable != NULL) + { + xnOSFreeAligned(m_pDepthToShiftTable); + m_pDepthToShiftTable = NULL; + m_bD2SAlloc = FALSE; + } + + return (XN_STATUS_OK); +} + +void XnRegistration::Apply(XnDepthPixel* pDM) +{ + XnUInt32 nDepthXRes = m_pDepthStream->GetXRes(); + XnUInt32 nDepthYRes = m_pDepthStream->GetYRes(); + + // copy buffer aside + xnOSMemCopy(m_pTempBuffer, pDM, nDepthXRes*nDepthYRes*sizeof(XnDepthPixel)); + + if (m_b1000) + { + Apply1000(m_pTempBuffer, pDM); + } + else + { + Apply1080(m_pTempBuffer, pDM); + } +} + +void XnRegistration::Apply1000(XnDepthPixel* pInput, XnDepthPixel* pOutput) +{ + XnUInt32 nDepthXRes = m_pDepthStream->GetXRes(); + XnUInt32 nDepthYRes = m_pDepthStream->GetYRes(); + + XnUInt16* pRegTable = m_pRegistrationTable; + XnUInt16* pDepth2ShiftTable = m_pDepthToShiftTable; + XnDepthPixel* pInputEnd = pInput + nDepthYRes*nDepthXRes; + XnDepthPixel nValue, nOutValue; + XnInt32 nNewX, nNewY; + XnUInt32 nArrPos; + + xnOSMemSet(pOutput, 0, m_pDepthStream->GetRequiredDataSize()); + + XnDouble dShiftFactor = m_dShiftFactor; + XnUInt32 nConstShift = m_pDepthStream->GetConstShift(); + + while (pInput != pInputEnd) + { + nValue = *pInput; + + if (nValue != 0) + { + nNewX = (XnInt32)(XnDouble(*pRegTable)/XN_REG_X_SCALE + XnInt32(pDepth2ShiftTable[nValue]/XN_REG_PARAB_COEFF - nConstShift) * dShiftFactor); + nNewY = *(pRegTable+1); + + if ( nNewX < nDepthXRes && nNewY < nDepthYRes ) + { + nArrPos = nNewY * nDepthXRes + nNewX; + nOutValue = pOutput[nArrPos]; + + if (nOutValue == 0 || nOutValue > nValue) + { + if ( nNewX > 0 && nNewY > 0 ) + { + pOutput[nArrPos-nDepthXRes] = nValue; + pOutput[nArrPos-nDepthXRes-1] = nValue; + pOutput[nArrPos-1] = nValue; + } + else if( nNewY > 0 ) + { + pOutput[nArrPos-nDepthXRes] = nValue; + } + else if( nNewX > 0 ) + { + pOutput[nArrPos-1] = nValue; + } + + pOutput[nArrPos] = nValue; + } + } + } + + pInput++; + pRegTable += 2; + } +} + +void XnRegistration::Apply1080(XnDepthPixel* pInput, XnDepthPixel* pOutput) +{ + XnInt16* pRegTable = (XnInt16*)m_pRegistrationTable; + XnInt16* pRGBRegDepthToShiftTable = (XnInt16*)m_pDepthToShiftTable; + XnDepthPixel nValue = 0; + XnDepthPixel nOutValue = 0; + XnUInt32 nNewX = 0; + XnUInt32 nNewY = 0; + XnUInt32 nArrPos = 0; + XnUInt32 nDepthXRes = XN_DEPTH_XRES; + XnUInt32 nDepthYRes = XN_DEPTH_YRES; + + memset(pOutput, XN_DEVICE_SENSOR_NO_DEPTH_VALUE, nDepthXRes*nDepthYRes*sizeof(XnDepthPixel)); + + // entire map should be shifted by X lines + XnUInt32 nConstOffset = nDepthYRes*m_padInfo.nStartLines; + + XnDepthPixel* pInputEnd = pInput + nDepthYRes*nDepthXRes; + + XnBool bMirror = m_pDepthStream->IsMirrored(); + + for (XnUInt32 y = 0; y < nDepthYRes; ++y) + { + pRegTable = (XnInt16*)&m_pRegistrationTable[ bMirror ? (y+1) * nDepthXRes * 2 - 2 : y * nDepthXRes * 2 ]; + for (XnUInt32 x = 0; x < nDepthXRes; ++x) + { + nValue = *pInput; + + if (nValue != XN_DEVICE_SENSOR_NO_DEPTH_VALUE) + { + nNewX = (XnUInt32)(*pRegTable + pRGBRegDepthToShiftTable[nValue]) / RGB_REG_X_VAL_SCALE; + nNewY = *(pRegTable+1); + + if (nNewX < nDepthXRes && nNewY < nDepthYRes ) + { + nArrPos = bMirror ? (nNewY+1)*nDepthXRes - nNewX - 2 : (nNewY*nDepthXRes) + nNewX; + nArrPos -= nConstOffset; + + nOutValue = pOutput[nArrPos]; + + if ((nOutValue == XN_DEVICE_SENSOR_NO_DEPTH_VALUE) || (nOutValue > nValue)) + { + if ( nNewX > 0 && nNewY > 0 ) + { + pOutput[nArrPos-nDepthXRes] = nValue; + pOutput[nArrPos-nDepthXRes-1] = nValue; + pOutput[nArrPos-1] = nValue; + } + else if( nNewY > 0 ) + { + pOutput[nArrPos-nDepthXRes] = nValue; + } + else if( nNewX > 0 ) + { + pOutput[nArrPos-1] = nValue; + } + + pOutput[nArrPos] = nValue; + } + } + } + + pInput++; + bMirror ? pRegTable-=2 : pRegTable+=2; + } + } +} diff --git a/Source/XnDeviceSensorV2/Registration.h b/Source/XnDeviceSensorV2/Registration.h index 8ed1a3e..52d3999 100644 --- a/Source/XnDeviceSensorV2/Registration.h +++ b/Source/XnDeviceSensorV2/Registration.h @@ -1,73 +1,73 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_REGISTRATION_H_ -#define _XN_REGISTRATION_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" - -#define XN_REG_PARAB_COEFF 4 -#define XN_REG_X_SCALE 16 - -class XnSensorDepthStream; // Forward Declaration - -class XnRegistration -{ -public: - XnRegistration(); - ~XnRegistration() { Free(); } - - XnStatus Init(XnDevicePrivateData* pDevicePrivateData, XnSensorDepthStream* pDepthStream, XnUInt16* pDepthToShiftTable); - XnStatus Free(); - void Apply(XnDepthPixel* pDM); - - inline XnBool IsInitialized() { return m_bInitialized; } - -private: - XnStatus BuildRegTable(); - XnStatus BuildRegTable1000(); - XnStatus BuildRegTable1080(); - void Apply1000(XnDepthPixel* pInput, XnDepthPixel* pOutput); - void Apply1080(XnDepthPixel* pInput, XnDepthPixel* pOutput); - - XnBool m_bInitialized; - - XnDevicePrivateData* m_pDevicePrivateData; - XnSensorDepthStream* m_pDepthStream; - XnUInt16* m_pDepthToShiftTable; - XnBool m_bD2SAlloc; - XnUInt16* m_pRegistrationTable; - XnRegistrationPaddingInformation m_padInfo; - XnDepthPixel* m_pTempBuffer; - XnDouble m_dShiftFactor; - XnBool m_b1000; -}; - -#endif //_XN_RGBREG_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_REGISTRATION_H_ +#define _XN_REGISTRATION_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" + +#define XN_REG_PARAB_COEFF 4 +#define XN_REG_X_SCALE 16 + +class XnSensorDepthStream; // Forward Declaration + +class XnRegistration +{ +public: + XnRegistration(); + ~XnRegistration() { Free(); } + + XnStatus Init(XnDevicePrivateData* pDevicePrivateData, XnSensorDepthStream* pDepthStream, XnUInt16* pDepthToShiftTable); + XnStatus Free(); + void Apply(XnDepthPixel* pDM); + + inline XnBool IsInitialized() { return m_bInitialized; } + +private: + XnStatus BuildRegTable(); + XnStatus BuildRegTable1000(); + XnStatus BuildRegTable1080(); + void Apply1000(XnDepthPixel* pInput, XnDepthPixel* pOutput); + void Apply1080(XnDepthPixel* pInput, XnDepthPixel* pOutput); + + XnBool m_bInitialized; + + XnDevicePrivateData* m_pDevicePrivateData; + XnSensorDepthStream* m_pDepthStream; + XnUInt16* m_pDepthToShiftTable; + XnBool m_bD2SAlloc; + XnUInt16* m_pRegistrationTable; + XnRegistrationPaddingInformation m_padInfo; + XnDepthPixel* m_pTempBuffer; + XnDouble m_dShiftFactor; + XnBool m_b1000; +}; + +#endif //_XN_RGBREG_H_ diff --git a/Source/XnDeviceSensorV2/Uncomp.cpp b/Source/XnDeviceSensorV2/Uncomp.cpp index 9b6edc4..8bbfb8e 100644 --- a/Source/XnDeviceSensorV2/Uncomp.cpp +++ b/Source/XnDeviceSensorV2/Uncomp.cpp @@ -1,320 +1,320 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "Uncomp.h" -#include -#include - -//--------------------------------------------------------------------------- -// Macros -//--------------------------------------------------------------------------- -#define XN_CHECK_UNC_IMAGE_OUTPUT(x, y) \ - if (x > y) \ - { \ - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); \ - } - -#define XN_IMAGE_OUTPUT(pOutput, pOutputEnd, nValue) \ - XN_CHECK_UNC_IMAGE_OUTPUT(pOutput, pOutputEnd) \ - *pOutput = nValue; \ - ++pOutput; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnStreamUncompressYUVImagePS(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, - XnUInt32* pnActualRead, XnBool bLastPart) -{ - // Input is made of 4-bit elements. - const XnUInt8* pInputOrig = pInput; - const XnUInt8* pInputEnd = pInput + nInputSize; - XnUInt8* pOrigOutput = pOutput; - XnUInt8* pOutputEnd = pOutput + (*pnOutputSize); - XnUInt8 nLastFullValue[4] = {0}; - - // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) - XnUInt32 nTempValue = 0; - XnUInt32 cInput = 0; - XnBool bReadByte = TRUE; - - if (nInputSize < sizeof(XnUInt8)) - { - printf("Buffer too small!\n"); - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - const XnUInt8* pInputLastPossibleStop = pInputOrig; - XnUInt8* pOutputLastPossibleStop = pOrigOutput; - - *pnActualRead = 0; - *pnOutputSize = 0; - - XnUInt32 nChannel = 0; - XnUInt32 nCurLineSize = 0; - - while (pInput < pInputEnd) - { - cInput = *pInput; - - if (bReadByte) - { - bReadByte = FALSE; - - if (cInput < 0xd0) // 0x0 to 0xc are diffs - { - // take high_element only - // diffs are between -6 and 6 (0x0 to 0xc) - nLastFullValue[nChannel] += (cInput >> 4) - 6; - } - else if (cInput < 0xe0) // 0xd is dummy - { - // Do nothing - continue; - } - else // 0xe is not used, so this must be 0xf - full - { - // take two more elements - nTempValue = (cInput & 0x0f) << 4; - - if (++pInput == pInputEnd) - break; - - nTempValue += (*pInput >> 4); - nLastFullValue[nChannel] = nTempValue; - } - } - else - { - // take low-element - cInput &= 0x0f; - bReadByte = TRUE; - pInput++; - - if (cInput < 0xd) // 0x0 to 0xc are diffs - { - // diffs are between -6 and 6 (0x0 to 0xc) - nLastFullValue[nChannel] += cInput - 6; - } - else if (cInput < 0xe) // 0xd is dummy - { - // Do nothing - continue; - } - else // 0xe is not in use, so this must be 0xf - full - { - if (pInput == pInputEnd) - break; - - // take two more elements - nLastFullValue[nChannel] = *pInput; - pInput++; - } - } - - // write output - if (pOutput > pOutputEnd) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - *pOutput = nLastFullValue[nChannel]; - pOutput++; - - nChannel++; - switch (nChannel) - { - case 2: - nLastFullValue[3] = nLastFullValue[1]; - break; - case 4: - nLastFullValue[1] = nLastFullValue[3]; - nChannel = 0; - break; - } - - nCurLineSize++; - if (nCurLineSize == nLineSize) - { - pInputLastPossibleStop = pInput; - pOutputLastPossibleStop = pOutput; - - nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0; - nCurLineSize = 0; - } - } - - if (bLastPart == TRUE) - { - *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt8); - *pnActualRead += (pInput - pInputOrig) * sizeof(XnUInt8); - } - else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig)) - { - *pnOutputSize = (pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8); - *pnActualRead += (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); - } - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnStreamUncompressImageNew(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, - XnUInt32* pnActualRead, XnBool bLastPart) -{ - // Input is made of 4-bit elements. - const XnUInt8* pInputOrig = pInput; - const XnUInt8* pInputEnd = pInput + nInputSize; - XnUInt8* pOrigOutput = pOutput; - XnUInt8* pOutputEnd = pOutput + (*pnOutputSize); - XnUInt8 nLastFullValue[4] = {0}; - - // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) - XnUInt32 nTempValue = 0; - XnUInt32 cInput = 0; - XnBool bReadByte = TRUE; - - if (nInputSize < sizeof(XnUInt8)) - { - printf("Buffer too small!\n"); - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - const XnUInt8* pInputLastPossibleStop = pInputOrig; - XnUInt8* pOutputLastPossibleStop = pOrigOutput; - - *pnActualRead = 0; - *pnOutputSize = 0; - - XnUInt32 nChannel = 0; - XnUInt32 nCurLineSize = 0; - - while (pInput < pInputEnd) - { - cInput = *pInput; - - if (bReadByte) - { - bReadByte = FALSE; - - if (cInput < 0xd0) // 0x0 to 0xc are diffs - { - // take high_element only - // diffs are between -6 and 6 (0x0 to 0xc) - nLastFullValue[nChannel] += (cInput >> 4) - 6; - } - else if (cInput < 0xe0) // 0xd is dummy - { - // Do nothing - continue; - } - else // 0xe is not used, so this must be 0xf - full - { - // take two more elements - nTempValue = (cInput & 0x0f) << 4; - - if (++pInput == pInputEnd) - break; - - nTempValue += (*pInput >> 4); - nLastFullValue[nChannel] = nTempValue; - } - } - else - { - // take low-element - cInput &= 0x0f; - bReadByte = TRUE; - pInput++; - - if (cInput < 0xd) // 0x0 to 0xc are diffs - { - // diffs are between -6 and 6 (0x0 to 0xc) - nLastFullValue[nChannel] += cInput - 6; - } - else if (cInput < 0xe) // 0xd is dummy - { - // Do nothing - continue; - } - else // 0xe is not in use, so this must be 0xf - full - { - if (pInput == pInputEnd) - break; - - // take two more elements - nLastFullValue[nChannel] = *pInput; - pInput++; - } - } - - // write output - if (pOutput > pOutputEnd) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - *pOutput = nLastFullValue[nChannel]; - pOutput++; - - nChannel++; - switch (nChannel) - { - case 2: - nChannel = 0; - break; - } - - nCurLineSize++; - if (nCurLineSize == nLineSize) - { - pInputLastPossibleStop = pInput; - pOutputLastPossibleStop = pOutput; - - nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0; - nCurLineSize = 0; - } - } - - if (bLastPart == TRUE) - { - *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt8); - *pnActualRead += (pInput - pInputOrig) * sizeof(XnUInt8); - } - else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig)) - { - *pnOutputSize = (pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8); - *pnActualRead += (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); - } - - // All is good... - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "Uncomp.h" +#include +#include + +//--------------------------------------------------------------------------- +// Macros +//--------------------------------------------------------------------------- +#define XN_CHECK_UNC_IMAGE_OUTPUT(x, y) \ + if (x > y) \ + { \ + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); \ + } + +#define XN_IMAGE_OUTPUT(pOutput, pOutputEnd, nValue) \ + XN_CHECK_UNC_IMAGE_OUTPUT(pOutput, pOutputEnd) \ + *pOutput = nValue; \ + ++pOutput; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnStreamUncompressYUVImagePS(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, + XnUInt32* pnActualRead, XnBool bLastPart) +{ + // Input is made of 4-bit elements. + const XnUInt8* pInputOrig = pInput; + const XnUInt8* pInputEnd = pInput + nInputSize; + XnUInt8* pOrigOutput = pOutput; + XnUInt8* pOutputEnd = pOutput + (*pnOutputSize); + XnUInt8 nLastFullValue[4] = {0}; + + // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) + XnUInt32 nTempValue = 0; + XnUInt32 cInput = 0; + XnBool bReadByte = TRUE; + + if (nInputSize < sizeof(XnUInt8)) + { + printf("Buffer too small!\n"); + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + const XnUInt8* pInputLastPossibleStop = pInputOrig; + XnUInt8* pOutputLastPossibleStop = pOrigOutput; + + *pnActualRead = 0; + *pnOutputSize = 0; + + XnUInt32 nChannel = 0; + XnUInt32 nCurLineSize = 0; + + while (pInput < pInputEnd) + { + cInput = *pInput; + + if (bReadByte) + { + bReadByte = FALSE; + + if (cInput < 0xd0) // 0x0 to 0xc are diffs + { + // take high_element only + // diffs are between -6 and 6 (0x0 to 0xc) + nLastFullValue[nChannel] += (cInput >> 4) - 6; + } + else if (cInput < 0xe0) // 0xd is dummy + { + // Do nothing + continue; + } + else // 0xe is not used, so this must be 0xf - full + { + // take two more elements + nTempValue = (cInput & 0x0f) << 4; + + if (++pInput == pInputEnd) + break; + + nTempValue += (*pInput >> 4); + nLastFullValue[nChannel] = nTempValue; + } + } + else + { + // take low-element + cInput &= 0x0f; + bReadByte = TRUE; + pInput++; + + if (cInput < 0xd) // 0x0 to 0xc are diffs + { + // diffs are between -6 and 6 (0x0 to 0xc) + nLastFullValue[nChannel] += cInput - 6; + } + else if (cInput < 0xe) // 0xd is dummy + { + // Do nothing + continue; + } + else // 0xe is not in use, so this must be 0xf - full + { + if (pInput == pInputEnd) + break; + + // take two more elements + nLastFullValue[nChannel] = *pInput; + pInput++; + } + } + + // write output + if (pOutput > pOutputEnd) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + *pOutput = nLastFullValue[nChannel]; + pOutput++; + + nChannel++; + switch (nChannel) + { + case 2: + nLastFullValue[3] = nLastFullValue[1]; + break; + case 4: + nLastFullValue[1] = nLastFullValue[3]; + nChannel = 0; + break; + } + + nCurLineSize++; + if (nCurLineSize == nLineSize) + { + pInputLastPossibleStop = pInput; + pOutputLastPossibleStop = pOutput; + + nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0; + nCurLineSize = 0; + } + } + + if (bLastPart == TRUE) + { + *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt8); + *pnActualRead += (pInput - pInputOrig) * sizeof(XnUInt8); + } + else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig)) + { + *pnOutputSize = (pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8); + *pnActualRead += (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); + } + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnStreamUncompressImageNew(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, + XnUInt32* pnActualRead, XnBool bLastPart) +{ + // Input is made of 4-bit elements. + const XnUInt8* pInputOrig = pInput; + const XnUInt8* pInputEnd = pInput + nInputSize; + XnUInt8* pOrigOutput = pOutput; + XnUInt8* pOutputEnd = pOutput + (*pnOutputSize); + XnUInt8 nLastFullValue[4] = {0}; + + // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) + XnUInt32 nTempValue = 0; + XnUInt32 cInput = 0; + XnBool bReadByte = TRUE; + + if (nInputSize < sizeof(XnUInt8)) + { + printf("Buffer too small!\n"); + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + const XnUInt8* pInputLastPossibleStop = pInputOrig; + XnUInt8* pOutputLastPossibleStop = pOrigOutput; + + *pnActualRead = 0; + *pnOutputSize = 0; + + XnUInt32 nChannel = 0; + XnUInt32 nCurLineSize = 0; + + while (pInput < pInputEnd) + { + cInput = *pInput; + + if (bReadByte) + { + bReadByte = FALSE; + + if (cInput < 0xd0) // 0x0 to 0xc are diffs + { + // take high_element only + // diffs are between -6 and 6 (0x0 to 0xc) + nLastFullValue[nChannel] += (cInput >> 4) - 6; + } + else if (cInput < 0xe0) // 0xd is dummy + { + // Do nothing + continue; + } + else // 0xe is not used, so this must be 0xf - full + { + // take two more elements + nTempValue = (cInput & 0x0f) << 4; + + if (++pInput == pInputEnd) + break; + + nTempValue += (*pInput >> 4); + nLastFullValue[nChannel] = nTempValue; + } + } + else + { + // take low-element + cInput &= 0x0f; + bReadByte = TRUE; + pInput++; + + if (cInput < 0xd) // 0x0 to 0xc are diffs + { + // diffs are between -6 and 6 (0x0 to 0xc) + nLastFullValue[nChannel] += cInput - 6; + } + else if (cInput < 0xe) // 0xd is dummy + { + // Do nothing + continue; + } + else // 0xe is not in use, so this must be 0xf - full + { + if (pInput == pInputEnd) + break; + + // take two more elements + nLastFullValue[nChannel] = *pInput; + pInput++; + } + } + + // write output + if (pOutput > pOutputEnd) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + *pOutput = nLastFullValue[nChannel]; + pOutput++; + + nChannel++; + switch (nChannel) + { + case 2: + nChannel = 0; + break; + } + + nCurLineSize++; + if (nCurLineSize == nLineSize) + { + pInputLastPossibleStop = pInput; + pOutputLastPossibleStop = pOutput; + + nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0; + nCurLineSize = 0; + } + } + + if (bLastPart == TRUE) + { + *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt8); + *pnActualRead += (pInput - pInputOrig) * sizeof(XnUInt8); + } + else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig)) + { + *pnOutputSize = (pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8); + *pnActualRead += (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); + } + + // All is good... + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/Uncomp.h b/Source/XnDeviceSensorV2/Uncomp.h index a34af76..f4068f8 100644 --- a/Source/XnDeviceSensorV2/Uncomp.h +++ b/Source/XnDeviceSensorV2/Uncomp.h @@ -1,50 +1,50 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_UNCOMP_H_ -#define _XN_UNCOMP_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -XnStatus XnStreamUncompressImageNew(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, - XnUInt32* pnActualRead, XnBool bLastPart); -XnStatus XnStreamUncompressYUVImagePS(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, - XnUInt32* pnActualRead, XnBool bLastPart); - -#endif //_XN_UNCOMP_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_UNCOMP_H_ +#define _XN_UNCOMP_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +XnStatus XnStreamUncompressImageNew(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, + XnUInt32* pnActualRead, XnBool bLastPart); +XnStatus XnStreamUncompressYUVImagePS(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize, + XnUInt32* pnActualRead, XnBool bLastPart); + +#endif //_XN_UNCOMP_H_ diff --git a/Source/XnDeviceSensorV2/XnAudioProcessor.cpp b/Source/XnDeviceSensorV2/XnAudioProcessor.cpp index f768383..4ba9533 100644 --- a/Source/XnDeviceSensorV2/XnAudioProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnAudioProcessor.cpp @@ -1,140 +1,140 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnAudioProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnAudioProcessor::XnAudioProcessor(XnSensorAudioStream* pStream, XnSensorStreamHelper* pHelper, XnUInt32 nInputPacketSize) : - XnWholePacketProcessor(pHelper->GetPrivateData(), pStream->GetType(), nInputPacketSize), - m_pStream(pStream), - m_pHelper(pHelper), - m_AudioInDump(XN_DUMP_CLOSED) -{ - xnDumpInit(&m_AudioInDump, XN_DUMP_AUDIO_IN, NULL, "AudioIn.pcm"); -} - -XnAudioProcessor::~XnAudioProcessor() -{ - xnDumpClose(&m_AudioInDump); - GetStream()->NumberOfChannelsProperty().OnChangeEvent().Unregister(m_hNumChannelsCallback); -} - -XnStatus XnAudioProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnWholePacketProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->NumberOfChannelsProperty().OnChangeEvent().Register(DeleteChannelChangedCallback, this, &m_hNumChannelsCallback); - XN_IS_STATUS_OK(nRetVal); - - CalcDeleteChannel(); - - return (XN_STATUS_OK); -} - -void XnAudioProcessor::ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData) -{ - XnInt32 nAvailableBytes = 0; - - xnOSEnterCriticalSection(&m_pDevicePrivateData->hAudioBufferCriticalSection); - - // take write packet - XnUChar* pWritePacket = m_pDevicePrivateData->pAudioBuffer + (m_pDevicePrivateData->nAudioWriteIndex * m_pDevicePrivateData->nAudioPacketSize); - - if (m_bDeleteChannel) - { - XnUInt16* pSamples = (XnUInt16*)pData; - XnUInt16* pSamplesEnd = (XnUInt16*)(pData + pHeader->nBufSize); - XnUInt16* pOutput = (XnUInt16*)pWritePacket; - - while (pSamples < pSamplesEnd) - { - *pOutput = *pSamples; - - pOutput++; - // skip a sample - pSamples += 2; - } - } - else - { - // copy data - xnOSMemCopy(pWritePacket, pData, pHeader->nBufSize); - } - - // mark timestamp - m_pDevicePrivateData->pAudioPacketsTimestamps[m_pDevicePrivateData->nAudioWriteIndex] = GetTimeStamp(pHeader->nTimeStamp); - - if (m_nLastPacketID % 10 == 0) - { - XnUInt64 nSysTime; - xnOSGetTimeStamp(&nSysTime); - - xnDumpWriteString(m_pDevicePrivateData->BandwidthDump, "%llu,%s,%d,%d\n", - nSysTime, "Audio", -1, m_nBytesReceived); - - m_nBytesReceived = 0; - } - - // move write index forward - m_pDevicePrivateData->nAudioWriteIndex = (m_pDevicePrivateData->nAudioWriteIndex + 1) % m_pDevicePrivateData->nAudioBufferNumOfPackets; - - // if write index got to read index (end of buffer), move read index forward (and loose a packet) - if (m_pDevicePrivateData->nAudioWriteIndex == m_pDevicePrivateData->nAudioReadIndex) - { - m_pDevicePrivateData->nAudioReadIndex = (m_pDevicePrivateData->nAudioReadIndex + 1) % m_pDevicePrivateData->nAudioBufferNumOfPackets; - } - - xnOSLeaveCriticalSection(&m_pDevicePrivateData->hAudioBufferCriticalSection); - - xnDumpWriteBuffer(m_AudioInDump, pData, pHeader->nBufSize); - - if (m_pDevicePrivateData->pAudioCallback != NULL) - { - m_pDevicePrivateData->pAudioCallback(m_pDevicePrivateData->pAudioCallbackCookie); - } -} - -void XnAudioProcessor::CalcDeleteChannel() -{ - m_bDeleteChannel = (m_pHelper->GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_2 && GetStream()->GetNumberOfChannels() == 1); -} - -XnStatus XnAudioProcessor::DeleteChannelChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnAudioProcessor* pThis = (XnAudioProcessor*)pCookie; - pThis->CalcDeleteChannel(); - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnAudioProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnAudioProcessor::XnAudioProcessor(XnSensorAudioStream* pStream, XnSensorStreamHelper* pHelper, XnUInt32 nInputPacketSize) : + XnWholePacketProcessor(pHelper->GetPrivateData(), pStream->GetType(), nInputPacketSize), + m_pStream(pStream), + m_pHelper(pHelper), + m_AudioInDump(XN_DUMP_CLOSED) +{ + xnDumpInit(&m_AudioInDump, XN_DUMP_AUDIO_IN, NULL, "AudioIn.pcm"); +} + +XnAudioProcessor::~XnAudioProcessor() +{ + xnDumpClose(&m_AudioInDump); + GetStream()->NumberOfChannelsProperty().OnChangeEvent().Unregister(m_hNumChannelsCallback); +} + +XnStatus XnAudioProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnWholePacketProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->NumberOfChannelsProperty().OnChangeEvent().Register(DeleteChannelChangedCallback, this, &m_hNumChannelsCallback); + XN_IS_STATUS_OK(nRetVal); + + CalcDeleteChannel(); + + return (XN_STATUS_OK); +} + +void XnAudioProcessor::ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData) +{ + XnInt32 nAvailableBytes = 0; + + xnOSEnterCriticalSection(&m_pDevicePrivateData->hAudioBufferCriticalSection); + + // take write packet + XnUChar* pWritePacket = m_pDevicePrivateData->pAudioBuffer + (m_pDevicePrivateData->nAudioWriteIndex * m_pDevicePrivateData->nAudioPacketSize); + + if (m_bDeleteChannel) + { + XnUInt16* pSamples = (XnUInt16*)pData; + XnUInt16* pSamplesEnd = (XnUInt16*)(pData + pHeader->nBufSize); + XnUInt16* pOutput = (XnUInt16*)pWritePacket; + + while (pSamples < pSamplesEnd) + { + *pOutput = *pSamples; + + pOutput++; + // skip a sample + pSamples += 2; + } + } + else + { + // copy data + xnOSMemCopy(pWritePacket, pData, pHeader->nBufSize); + } + + // mark timestamp + m_pDevicePrivateData->pAudioPacketsTimestamps[m_pDevicePrivateData->nAudioWriteIndex] = GetTimeStamp(pHeader->nTimeStamp); + + if (m_nLastPacketID % 10 == 0) + { + XnUInt64 nSysTime; + xnOSGetTimeStamp(&nSysTime); + + xnDumpWriteString(m_pDevicePrivateData->BandwidthDump, "%llu,%s,%d,%d\n", + nSysTime, "Audio", -1, m_nBytesReceived); + + m_nBytesReceived = 0; + } + + // move write index forward + m_pDevicePrivateData->nAudioWriteIndex = (m_pDevicePrivateData->nAudioWriteIndex + 1) % m_pDevicePrivateData->nAudioBufferNumOfPackets; + + // if write index got to read index (end of buffer), move read index forward (and loose a packet) + if (m_pDevicePrivateData->nAudioWriteIndex == m_pDevicePrivateData->nAudioReadIndex) + { + m_pDevicePrivateData->nAudioReadIndex = (m_pDevicePrivateData->nAudioReadIndex + 1) % m_pDevicePrivateData->nAudioBufferNumOfPackets; + } + + xnOSLeaveCriticalSection(&m_pDevicePrivateData->hAudioBufferCriticalSection); + + xnDumpWriteBuffer(m_AudioInDump, pData, pHeader->nBufSize); + + if (m_pDevicePrivateData->pAudioCallback != NULL) + { + m_pDevicePrivateData->pAudioCallback(m_pDevicePrivateData->pAudioCallbackCookie); + } +} + +void XnAudioProcessor::CalcDeleteChannel() +{ + m_bDeleteChannel = (m_pHelper->GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_2 && GetStream()->GetNumberOfChannels() == 1); +} + +XnStatus XnAudioProcessor::DeleteChannelChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnAudioProcessor* pThis = (XnAudioProcessor*)pCookie; + pThis->CalcDeleteChannel(); + return XN_STATUS_OK; +} diff --git a/Source/XnDeviceSensorV2/XnAudioProcessor.h b/Source/XnDeviceSensorV2/XnAudioProcessor.h index 4395240..7cf4c0f 100644 --- a/Source/XnDeviceSensorV2/XnAudioProcessor.h +++ b/Source/XnDeviceSensorV2/XnAudioProcessor.h @@ -1,75 +1,75 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_AUDIO_PROCESSOR_H__ -#define __XN_AUDIO_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnWholePacketProcessor.h" -#include "XnSensorAudioStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnAudioProcessor : public XnWholePacketProcessor -{ -public: - XnAudioProcessor(XnSensorAudioStream* pStream, XnSensorStreamHelper* pHelper, XnUInt32 nInputPacketSize); - ~XnAudioProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData); - - inline XnSensorAudioStream* GetStream() - { - return m_pStream; - } - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - void CalcDeleteChannel(); - static XnStatus XN_CALLBACK_TYPE DeleteChannelChangedCallback(const XnProperty* pSender, void* pCookie); - - /** Used to dump Audio In data. */ - XnDump m_AudioInDump; - XnBool m_bDeleteChannel; - XnSensorAudioStream* m_pStream; - XnSensorStreamHelper* m_pHelper; - - XnCallbackHandle m_hNumChannelsCallback; -}; - -#endif //__XN_AUDIO_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_AUDIO_PROCESSOR_H__ +#define __XN_AUDIO_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnWholePacketProcessor.h" +#include "XnSensorAudioStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnAudioProcessor : public XnWholePacketProcessor +{ +public: + XnAudioProcessor(XnSensorAudioStream* pStream, XnSensorStreamHelper* pHelper, XnUInt32 nInputPacketSize); + ~XnAudioProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData); + + inline XnSensorAudioStream* GetStream() + { + return m_pStream; + } + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + void CalcDeleteChannel(); + static XnStatus XN_CALLBACK_TYPE DeleteChannelChangedCallback(const XnProperty* pSender, void* pCookie); + + /** Used to dump Audio In data. */ + XnDump m_AudioInDump; + XnBool m_bDeleteChannel; + XnSensorAudioStream* m_pStream; + XnSensorStreamHelper* m_pHelper; + + XnCallbackHandle m_hNumChannelsCallback; +}; + +#endif //__XN_AUDIO_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnBayerImageProcessor.cpp b/Source/XnDeviceSensorV2/XnBayerImageProcessor.cpp index 20a5d15..c218427 100644 --- a/Source/XnDeviceSensorV2/XnBayerImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnBayerImageProcessor.cpp @@ -1,163 +1,163 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnBayerImageProcessor.h" -#include "Uncomp.h" -#include "Bayer.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnBayerImageProcessor::XnBayerImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnBayerImageProcessor::~XnBayerImageProcessor() -{ -} - -XnStatus XnBayerImageProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnImageProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, GetExpectedOutputSize()); - - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - break; - case XN_OUTPUT_FORMAT_RGB24: - XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedBayerBuffer, GetExpectedOutputSize()); - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); - } - - return (XN_STATUS_OK); -} - -void XnBayerImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnBayerImageProcessor::ProcessFramePacketChunk") - - // if output format is Gray8, we can write directly to output buffer. otherwise, we need - // to write to a temp buffer. - XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE8) ? GetWriteBuffer() : &m_UncompressedBayerBuffer; - - const XnUChar* pBuf = NULL; - XnUInt32 nBufSize = 0; - - // check if we have bytes stored from previous calls - if (m_ContinuousBuffer.GetSize() > 0) - { - // we have no choice. We need to append current buffer to previous bytes - if (m_ContinuousBuffer.GetFreeSpaceInBuffer() < nDataSize) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow image! %d", m_ContinuousBuffer.GetSize()); - FrameIsCorrupted(); - } - else - { - m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); - } - - pBuf = m_ContinuousBuffer.GetData(); - nBufSize = m_ContinuousBuffer.GetSize(); - } - else - { - // we can process the data directly - pBuf = pData; - nBufSize = nDataSize; - } - - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - XnUInt32 nWrittenOutput = nOutputSize; - XnUInt32 nActualRead = 0; - XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END && (nDataOffset + nDataSize) == pHeader->nBufSize; - XnStatus nRetVal = XnStreamUncompressImageNew(pBuf, nBufSize, pWriteBuffer->GetUnsafeWritePointer(), - &nWrittenOutput, GetActualXRes(), &nActualRead, bLastPart); - - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Image decompression failed: %s (%d of %d, requested %d, last %d)", xnGetStatusString(nRetVal), nWrittenOutput, nBufSize, nOutputSize, bLastPart); - FrameIsCorrupted(); - } - - pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); - - nBufSize -= nActualRead; - m_ContinuousBuffer.Reset(); - - // if we have any bytes left, keep them for next time - if (nBufSize > 0) - { - pBuf += nActualRead; - m_ContinuousBuffer.UnsafeWrite(pBuf, nBufSize); - } - - XN_PROFILING_END_SECTION -} - -void XnBayerImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnImageProcessor::OnStartOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} - -void XnBayerImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XN_PROFILING_START_SECTION("XnBayerImageProcessor::OnEndOfFrame") - - // if data was written to temp buffer, convert it now - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - break; - case XN_OUTPUT_FORMAT_RGB24: - { - Bayer2RGB888(m_UncompressedBayerBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), GetActualXRes(), GetActualYRes(), 1, 0); - GetWriteBuffer()->UnsafeUpdateSize(GetActualXRes()*GetActualYRes()*3); - m_UncompressedBayerBuffer.Reset(); - } - break; - } - - XnImageProcessor::OnEndOfFrame(pHeader); - m_ContinuousBuffer.Reset(); - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnBayerImageProcessor.h" +#include "Uncomp.h" +#include "Bayer.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnBayerImageProcessor::XnBayerImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnBayerImageProcessor::~XnBayerImageProcessor() +{ +} + +XnStatus XnBayerImageProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnImageProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, GetExpectedOutputSize()); + + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + break; + case XN_OUTPUT_FORMAT_RGB24: + XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedBayerBuffer, GetExpectedOutputSize()); + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); + } + + return (XN_STATUS_OK); +} + +void XnBayerImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnBayerImageProcessor::ProcessFramePacketChunk") + + // if output format is Gray8, we can write directly to output buffer. otherwise, we need + // to write to a temp buffer. + XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE8) ? GetWriteBuffer() : &m_UncompressedBayerBuffer; + + const XnUChar* pBuf = NULL; + XnUInt32 nBufSize = 0; + + // check if we have bytes stored from previous calls + if (m_ContinuousBuffer.GetSize() > 0) + { + // we have no choice. We need to append current buffer to previous bytes + if (m_ContinuousBuffer.GetFreeSpaceInBuffer() < nDataSize) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow image! %d", m_ContinuousBuffer.GetSize()); + FrameIsCorrupted(); + } + else + { + m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); + } + + pBuf = m_ContinuousBuffer.GetData(); + nBufSize = m_ContinuousBuffer.GetSize(); + } + else + { + // we can process the data directly + pBuf = pData; + nBufSize = nDataSize; + } + + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + XnUInt32 nWrittenOutput = nOutputSize; + XnUInt32 nActualRead = 0; + XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END && (nDataOffset + nDataSize) == pHeader->nBufSize; + XnStatus nRetVal = XnStreamUncompressImageNew(pBuf, nBufSize, pWriteBuffer->GetUnsafeWritePointer(), + &nWrittenOutput, GetActualXRes(), &nActualRead, bLastPart); + + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Image decompression failed: %s (%d of %d, requested %d, last %d)", xnGetStatusString(nRetVal), nWrittenOutput, nBufSize, nOutputSize, bLastPart); + FrameIsCorrupted(); + } + + pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); + + nBufSize -= nActualRead; + m_ContinuousBuffer.Reset(); + + // if we have any bytes left, keep them for next time + if (nBufSize > 0) + { + pBuf += nActualRead; + m_ContinuousBuffer.UnsafeWrite(pBuf, nBufSize); + } + + XN_PROFILING_END_SECTION +} + +void XnBayerImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnImageProcessor::OnStartOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} + +void XnBayerImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XN_PROFILING_START_SECTION("XnBayerImageProcessor::OnEndOfFrame") + + // if data was written to temp buffer, convert it now + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + break; + case XN_OUTPUT_FORMAT_RGB24: + { + Bayer2RGB888(m_UncompressedBayerBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), GetActualXRes(), GetActualYRes(), 1, 0); + GetWriteBuffer()->UnsafeUpdateSize(GetActualXRes()*GetActualYRes()*3); + m_UncompressedBayerBuffer.Reset(); + } + break; + } + + XnImageProcessor::OnEndOfFrame(pHeader); + m_ContinuousBuffer.Reset(); + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnBayerImageProcessor.h b/Source/XnDeviceSensorV2/XnBayerImageProcessor.h index a779587..3e1cd6c 100644 --- a/Source/XnDeviceSensorV2/XnBayerImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnBayerImageProcessor.h @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_BAYER_IMAGE_PROCESSOR_H__ -#define __XN_BAYER_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnBayerImageProcessor : public XnImageProcessor -{ -public: - XnBayerImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnBayerImageProcessor(); - - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - XnBuffer m_ContinuousBuffer; - XnBuffer m_UncompressedBayerBuffer; -}; - -#endif //__XN_BAYER_IMAGE_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_BAYER_IMAGE_PROCESSOR_H__ +#define __XN_BAYER_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnBayerImageProcessor : public XnImageProcessor +{ +public: + XnBayerImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnBayerImageProcessor(); + + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + XnBuffer m_ContinuousBuffer; + XnBuffer m_UncompressedBayerBuffer; +}; + +#endif //__XN_BAYER_IMAGE_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnCmosInfo.cpp b/Source/XnDeviceSensorV2/XnCmosInfo.cpp index 6e5b243..d8c7c28 100644 --- a/Source/XnDeviceSensorV2/XnCmosInfo.cpp +++ b/Source/XnDeviceSensorV2/XnCmosInfo.cpp @@ -1,87 +1,87 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCmosInfo.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnCmosInfo::XnCmosInfo(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData) : - m_pFirmware(pFirmware), - m_pDevicePrivateData(pDevicePrivateData) -{} - -XnCmosInfo::~XnCmosInfo() -{ -} - -XnStatus XnCmosInfo::SetCmosConfig(XnCMOSType nCmos, XnResolutions nResolution, XnUInt32 nFPS) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_pFirmware->GetInfo()->nFWVer >= XN_SENSOR_FW_VER_5_1) - { - // take blanking info - XnCmosBlankingInformation* pInfo = NULL; - - // search the list if we already have this info - for (XnCmosBlankingDataList::Iterator it = m_CmosBlankingInfo.begin(); it != m_CmosBlankingInfo.end(); ++it) - { - XnCmosBlankingData& data = *it; - if (data.nRes == nResolution && data.nFPS == nFPS) - { - pInfo = &data.BlankingInfo; - break; - } - } - - if (pInfo == NULL) - { - // not found in list. fetch it from FW - XnCmosBlankingData data; - data.nRes = nResolution; - data.nFPS = nFPS; - - nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_BLANKING, &data.BlankingInfo, sizeof(XnCmosBlankingInformation), nResolution, nFPS); - XN_IS_STATUS_OK(nRetVal); - - // add to list - nRetVal = m_CmosBlankingInfo.AddFirst(data); - XN_IS_STATUS_OK(nRetVal); - - // take its info (take a pointer to the object in the list, and not to the one on the stack) - pInfo = &m_CmosBlankingInfo.begin()->BlankingInfo; - } - - m_pCurrCmosBlankingInfo[nCmos] = &pInfo->Coefficients[nCmos]; - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCmosInfo.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnCmosInfo::XnCmosInfo(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData) : + m_pFirmware(pFirmware), + m_pDevicePrivateData(pDevicePrivateData) +{} + +XnCmosInfo::~XnCmosInfo() +{ +} + +XnStatus XnCmosInfo::SetCmosConfig(XnCMOSType nCmos, XnResolutions nResolution, XnUInt32 nFPS) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pFirmware->GetInfo()->nFWVer >= XN_SENSOR_FW_VER_5_1) + { + // take blanking info + XnCmosBlankingInformation* pInfo = NULL; + + // search the list if we already have this info + for (XnCmosBlankingDataList::Iterator it = m_CmosBlankingInfo.begin(); it != m_CmosBlankingInfo.end(); ++it) + { + XnCmosBlankingData& data = *it; + if (data.nRes == nResolution && data.nFPS == nFPS) + { + pInfo = &data.BlankingInfo; + break; + } + } + + if (pInfo == NULL) + { + // not found in list. fetch it from FW + XnCmosBlankingData data; + data.nRes = nResolution; + data.nFPS = nFPS; + + nRetVal = XnHostProtocolAlgorithmParams(m_pDevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_BLANKING, &data.BlankingInfo, sizeof(XnCmosBlankingInformation), nResolution, nFPS); + XN_IS_STATUS_OK(nRetVal); + + // add to list + nRetVal = m_CmosBlankingInfo.AddFirst(data); + XN_IS_STATUS_OK(nRetVal); + + // take its info (take a pointer to the object in the list, and not to the one on the stack) + pInfo = &m_CmosBlankingInfo.begin()->BlankingInfo; + } + + m_pCurrCmosBlankingInfo[nCmos] = &pInfo->Coefficients[nCmos]; + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/XnCmosInfo.h b/Source/XnDeviceSensorV2/XnCmosInfo.h index 588c3e4..0deb8f9 100644 --- a/Source/XnDeviceSensorV2/XnCmosInfo.h +++ b/Source/XnDeviceSensorV2/XnCmosInfo.h @@ -1,65 +1,65 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_CMOS_INFO_H__ -#define __XN_CMOS_INFO_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFirmware.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct -{ - XnCmosBlankingInformation BlankingInfo; - XnResolutions nRes; - XnUInt32 nFPS; -} XnCmosBlankingData; - -class XnCmosInfo -{ -public: - XnCmosInfo(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData); - ~XnCmosInfo(); - - XnStatus SetCmosConfig(XnCMOSType nCmos, XnResolutions nResolution, XnUInt32 nFPS); - - inline const XnCmosBlankingCoefficients* GetBlankingCoefficients(XnCMOSType nCmos) const { return m_pCurrCmosBlankingInfo[nCmos]; } - -private: - XN_DECLARE_LIST(XnCmosBlankingData, XnCmosBlankingDataList) - - XnSensorFirmware* m_pFirmware; - XnDevicePrivateData* m_pDevicePrivateData; - - XnCmosBlankingDataList m_CmosBlankingInfo; - XnCmosBlankingCoefficients* m_pCurrCmosBlankingInfo[XN_CMOS_COUNT]; -}; - -#endif //__XN_CMOS_INFO_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_CMOS_INFO_H__ +#define __XN_CMOS_INFO_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFirmware.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct +{ + XnCmosBlankingInformation BlankingInfo; + XnResolutions nRes; + XnUInt32 nFPS; +} XnCmosBlankingData; + +class XnCmosInfo +{ +public: + XnCmosInfo(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData); + ~XnCmosInfo(); + + XnStatus SetCmosConfig(XnCMOSType nCmos, XnResolutions nResolution, XnUInt32 nFPS); + + inline const XnCmosBlankingCoefficients* GetBlankingCoefficients(XnCMOSType nCmos) const { return m_pCurrCmosBlankingInfo[nCmos]; } + +private: + XN_DECLARE_LIST(XnCmosBlankingData, XnCmosBlankingDataList) + + XnSensorFirmware* m_pFirmware; + XnDevicePrivateData* m_pDevicePrivateData; + + XnCmosBlankingDataList m_CmosBlankingInfo; + XnCmosBlankingCoefficients* m_pCurrCmosBlankingInfo[XN_CMOS_COUNT]; +}; + +#endif //__XN_CMOS_INFO_H__ diff --git a/Source/XnDeviceSensorV2/XnDataProcessor.cpp b/Source/XnDeviceSensorV2/XnDataProcessor.cpp index 49fd1a0..c0bf3bb 100644 --- a/Source/XnDeviceSensorV2/XnDataProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnDataProcessor.cpp @@ -1,193 +1,193 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessor.h" -#include -#include "XnSensor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDataProcessor::XnDataProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName) : - m_pDevicePrivateData(pDevicePrivateData), - m_csName(csName), - m_nLastPacketID(0), - m_nBytesReceived(0) -{ - m_TimeStampData.csStreamName = csName; - m_TimeStampData.bFirst = TRUE; -} - -XnDataProcessor::~XnDataProcessor() -{} - -XnStatus XnDataProcessor::Init() -{ - return (XN_STATUS_OK); -} - -void XnDataProcessor::ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnDataProcessor::ProcessData") - - // count these bytes - m_nBytesReceived += nDataSize; - - // check if we start a new packet - if (nDataOffset == 0) - { - // make sure no packet was lost - if (pHeader->nReserve != m_nLastPacketID+1 && pHeader->nReserve != 0) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s: Expected %x, got %x", m_csName, m_nLastPacketID+1, pHeader->nReserve); - OnPacketLost(); - } - - m_nLastPacketID = pHeader->nReserve; - - // log packet arrival - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - xnDumpWriteString(m_pDevicePrivateData->MiniPacketsDump, "%llu,0x%hx,0x%hx,0x%hx,%u\n", nNow, pHeader->nType, pHeader->nReserve, pHeader->nBufSize, pHeader->nTimeStamp); - } - - ProcessPacketChunk(pHeader, pData, nDataOffset, nDataSize); - - XN_PROFILING_END_SECTION -} - -void XnDataProcessor::OnPacketLost() -{} - -XnUInt64 XnDataProcessor::GetTimeStamp(XnUInt32 nDeviceTimeStamp) -{ - const XnUInt64 nWrapPoint = ((XnUInt64)XN_MAX_UINT32) + 1; - XnUInt64 nResultInTicks; - - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - - XnChar csDumpComment[200] = ""; - - XnBool bCheckSanity = TRUE; - - // we register the first TS calculated as time-zero. Every stream's TS data will be - // synchronized with it - if (m_pDevicePrivateData->nGlobalReferenceTS == 0) - { - xnOSEnterCriticalSection(&m_pDevicePrivateData->hEndPointsCS); - if (m_pDevicePrivateData->nGlobalReferenceTS == 0) - { - m_pDevicePrivateData->nGlobalReferenceTS = nDeviceTimeStamp; - m_pDevicePrivateData->nGlobalReferenceOSTime = nNow; - } - xnOSLeaveCriticalSection(&m_pDevicePrivateData->hEndPointsCS); - } - - if (m_TimeStampData.bFirst) - { - // check how much OS time passed since global reference was taken - XnUInt64 nOSTime = nNow - m_pDevicePrivateData->nGlobalReferenceOSTime; - - // check how many full wrap-arounds occurred (according to OS time) - XnFloat fWrapAroundInMicroseconds = nWrapPoint / (XnDouble)m_pDevicePrivateData->fDeviceFrequency; - XnUInt32 nWraps = nOSTime / fWrapAroundInMicroseconds; // floor - - // now check, if current timestamp is less than global, then we have one more wrap-around - // (make sure it's significant - we allow up to 10 ms before - otherwise it could just be a - // matter of race-condition) - if (m_pDevicePrivateData->nGlobalReferenceTS > nDeviceTimeStamp && - nOSTime > XN_SENSOR_TIMESTAMP_SANITY_DIFF*1000) - { - ++nWraps; - } - - m_TimeStampData.nReferenceTS = m_pDevicePrivateData->nGlobalReferenceTS; - m_TimeStampData.nTotalTicksAtReferenceTS = nWrapPoint * nWraps; - m_TimeStampData.nLastDeviceTS = 0; - m_TimeStampData.bFirst = FALSE; - nResultInTicks = 0; - bCheckSanity = FALSE; // no need. - sprintf(csDumpComment, "Init. Total Ticks in Ref TS: %llu", m_TimeStampData.nTotalTicksAtReferenceTS); - } - - if (nDeviceTimeStamp > m_TimeStampData.nLastDeviceTS) // this is the normal case - { - nResultInTicks = m_TimeStampData.nTotalTicksAtReferenceTS + nDeviceTimeStamp - m_TimeStampData.nReferenceTS; - } - else // wrap around occurred - { - // add the passed time to the reference time - m_TimeStampData.nTotalTicksAtReferenceTS += (nWrapPoint + nDeviceTimeStamp - m_TimeStampData.nReferenceTS); - // mark reference timestamp - m_TimeStampData.nReferenceTS = nDeviceTimeStamp; - - sprintf(csDumpComment, "Wrap around. Refernce TS: %u / TotalTicksAtReference: %llu", m_TimeStampData.nReferenceTS, m_TimeStampData.nTotalTicksAtReferenceTS); - - nResultInTicks = m_TimeStampData.nTotalTicksAtReferenceTS; - } - - m_TimeStampData.nLastDeviceTS = nDeviceTimeStamp; - - // calculate result in microseconds - // NOTE: Intel compiler does too much optimization, and we loose up to 5 milliseconds. We perform - // the entire calculation in XnDouble as a workaround - XnDouble dResultTimeMicroSeconds = (XnDouble)nResultInTicks / (XnDouble)m_pDevicePrivateData->fDeviceFrequency; - XnUInt64 nResultTimeMilliSeconds = (XnUInt64)(dResultTimeMicroSeconds / 1000.0); - - XnBool bIsSane = TRUE; - - // perform sanity check - if (bCheckSanity && (nResultTimeMilliSeconds > (m_TimeStampData.nLastResultTime + XN_SENSOR_TIMESTAMP_SANITY_DIFF*1000))) - { - bIsSane = FALSE; - sprintf(csDumpComment, "%s,Didn't pass sanity. Will try to re-sync.", csDumpComment); - } - - // calc result - XnUInt64 nResult = (m_pDevicePrivateData->pSensor->IsHighResTimestamps() ? (XnUInt64)dResultTimeMicroSeconds : nResultTimeMilliSeconds); - - // dump it - xnDumpWriteString(m_pDevicePrivateData->TimestampsDump, "%llu,%s,%u,%llu,%s\n", nNow, m_TimeStampData.csStreamName, nDeviceTimeStamp, nResult, csDumpComment); - - if (bIsSane) - { - m_TimeStampData.nLastResultTime = nResultTimeMilliSeconds; - return (nResult); - } - else - { - // sanity failed. We lost sync. restart - m_TimeStampData.bFirst = TRUE; - return GetTimeStamp(nDeviceTimeStamp); - } -} - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessor.h" +#include +#include "XnSensor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDataProcessor::XnDataProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName) : + m_pDevicePrivateData(pDevicePrivateData), + m_csName(csName), + m_nLastPacketID(0), + m_nBytesReceived(0) +{ + m_TimeStampData.csStreamName = csName; + m_TimeStampData.bFirst = TRUE; +} + +XnDataProcessor::~XnDataProcessor() +{} + +XnStatus XnDataProcessor::Init() +{ + return (XN_STATUS_OK); +} + +void XnDataProcessor::ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnDataProcessor::ProcessData") + + // count these bytes + m_nBytesReceived += nDataSize; + + // check if we start a new packet + if (nDataOffset == 0) + { + // make sure no packet was lost + if (pHeader->nReserve != m_nLastPacketID+1 && pHeader->nReserve != 0) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s: Expected %x, got %x", m_csName, m_nLastPacketID+1, pHeader->nReserve); + OnPacketLost(); + } + + m_nLastPacketID = pHeader->nReserve; + + // log packet arrival + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_pDevicePrivateData->MiniPacketsDump, "%llu,0x%hx,0x%hx,0x%hx,%u\n", nNow, pHeader->nType, pHeader->nReserve, pHeader->nBufSize, pHeader->nTimeStamp); + } + + ProcessPacketChunk(pHeader, pData, nDataOffset, nDataSize); + + XN_PROFILING_END_SECTION +} + +void XnDataProcessor::OnPacketLost() +{} + +XnUInt64 XnDataProcessor::GetTimeStamp(XnUInt32 nDeviceTimeStamp) +{ + const XnUInt64 nWrapPoint = ((XnUInt64)XN_MAX_UINT32) + 1; + XnUInt64 nResultInTicks; + + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + + XnChar csDumpComment[200] = ""; + + XnBool bCheckSanity = TRUE; + + // we register the first TS calculated as time-zero. Every stream's TS data will be + // synchronized with it + if (m_pDevicePrivateData->nGlobalReferenceTS == 0) + { + xnOSEnterCriticalSection(&m_pDevicePrivateData->hEndPointsCS); + if (m_pDevicePrivateData->nGlobalReferenceTS == 0) + { + m_pDevicePrivateData->nGlobalReferenceTS = nDeviceTimeStamp; + m_pDevicePrivateData->nGlobalReferenceOSTime = nNow; + } + xnOSLeaveCriticalSection(&m_pDevicePrivateData->hEndPointsCS); + } + + if (m_TimeStampData.bFirst) + { + // check how much OS time passed since global reference was taken + XnUInt64 nOSTime = nNow - m_pDevicePrivateData->nGlobalReferenceOSTime; + + // check how many full wrap-arounds occurred (according to OS time) + XnFloat fWrapAroundInMicroseconds = nWrapPoint / (XnDouble)m_pDevicePrivateData->fDeviceFrequency; + XnUInt32 nWraps = nOSTime / fWrapAroundInMicroseconds; // floor + + // now check, if current timestamp is less than global, then we have one more wrap-around + // (make sure it's significant - we allow up to 10 ms before - otherwise it could just be a + // matter of race-condition) + if (m_pDevicePrivateData->nGlobalReferenceTS > nDeviceTimeStamp && + nOSTime > XN_SENSOR_TIMESTAMP_SANITY_DIFF*1000) + { + ++nWraps; + } + + m_TimeStampData.nReferenceTS = m_pDevicePrivateData->nGlobalReferenceTS; + m_TimeStampData.nTotalTicksAtReferenceTS = nWrapPoint * nWraps; + m_TimeStampData.nLastDeviceTS = 0; + m_TimeStampData.bFirst = FALSE; + nResultInTicks = 0; + bCheckSanity = FALSE; // no need. + sprintf(csDumpComment, "Init. Total Ticks in Ref TS: %llu", m_TimeStampData.nTotalTicksAtReferenceTS); + } + + if (nDeviceTimeStamp > m_TimeStampData.nLastDeviceTS) // this is the normal case + { + nResultInTicks = m_TimeStampData.nTotalTicksAtReferenceTS + nDeviceTimeStamp - m_TimeStampData.nReferenceTS; + } + else // wrap around occurred + { + // add the passed time to the reference time + m_TimeStampData.nTotalTicksAtReferenceTS += (nWrapPoint + nDeviceTimeStamp - m_TimeStampData.nReferenceTS); + // mark reference timestamp + m_TimeStampData.nReferenceTS = nDeviceTimeStamp; + + sprintf(csDumpComment, "Wrap around. Refernce TS: %u / TotalTicksAtReference: %llu", m_TimeStampData.nReferenceTS, m_TimeStampData.nTotalTicksAtReferenceTS); + + nResultInTicks = m_TimeStampData.nTotalTicksAtReferenceTS; + } + + m_TimeStampData.nLastDeviceTS = nDeviceTimeStamp; + + // calculate result in microseconds + // NOTE: Intel compiler does too much optimization, and we loose up to 5 milliseconds. We perform + // the entire calculation in XnDouble as a workaround + XnDouble dResultTimeMicroSeconds = (XnDouble)nResultInTicks / (XnDouble)m_pDevicePrivateData->fDeviceFrequency; + XnUInt64 nResultTimeMilliSeconds = (XnUInt64)(dResultTimeMicroSeconds / 1000.0); + + XnBool bIsSane = TRUE; + + // perform sanity check + if (bCheckSanity && (nResultTimeMilliSeconds > (m_TimeStampData.nLastResultTime + XN_SENSOR_TIMESTAMP_SANITY_DIFF*1000))) + { + bIsSane = FALSE; + sprintf(csDumpComment, "%s,Didn't pass sanity. Will try to re-sync.", csDumpComment); + } + + // calc result + XnUInt64 nResult = (m_pDevicePrivateData->pSensor->IsHighResTimestamps() ? (XnUInt64)dResultTimeMicroSeconds : nResultTimeMilliSeconds); + + // dump it + xnDumpWriteString(m_pDevicePrivateData->TimestampsDump, "%llu,%s,%u,%llu,%s\n", nNow, m_TimeStampData.csStreamName, nDeviceTimeStamp, nResult, csDumpComment); + + if (bIsSane) + { + m_TimeStampData.nLastResultTime = nResultTimeMilliSeconds; + return (nResult); + } + else + { + // sanity failed. We lost sync. restart + m_TimeStampData.bFirst = TRUE; + return GetTimeStamp(nDeviceTimeStamp); + } +} + + diff --git a/Source/XnDeviceSensorV2/XnDataProcessor.h b/Source/XnDeviceSensorV2/XnDataProcessor.h index c738042..852eb80 100644 --- a/Source/XnDeviceSensorV2/XnDataProcessor.h +++ b/Source/XnDeviceSensorV2/XnDataProcessor.h @@ -1,103 +1,103 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DATA_PROCESSOR_H__ -#define __XN_DATA_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" -#include "XnDeviceSensorProtocol.h" -#include - -/** -* Base class for all data processors. -*/ -class XnDataProcessor -{ -public: - XnDataProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName); - virtual ~XnDataProcessor(); - -//--------------------------------------------------------------------------- -// Methods -//--------------------------------------------------------------------------- -public: - /** - * Initializes a Data Processor. - * - * @param pDevicePrivateData [in] A pointer to the device. - * @param csName [in] The name of the stream. - */ - virtual XnStatus Init(); - - /** - * Handles some data from this stream. - * - * @param pHeader [in] A pointer to current packet header. - * @param pData [in] A pointer to the data. - * @param nDataOffset [in] The offset of this data chunk inside current packet. - * @param nDataSize [in] Size of the data in bytes. - */ - void ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - -//--------------------------------------------------------------------------- -// Virtual Functions -//--------------------------------------------------------------------------- -protected: - virtual void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) = 0; - virtual void OnPacketLost(); - -//--------------------------------------------------------------------------- -// Utility Functions -//--------------------------------------------------------------------------- -protected: - /* - * Gets a calculated timestamp from the device timestamp. - * - * @param nDeviceTimeStamp [in] The device TS to translate. - */ - XnUInt64 GetTimeStamp(XnUInt32 nDeviceTimeStamp); - -//--------------------------------------------------------------------------- -// Class Members -//--------------------------------------------------------------------------- -protected: - XnDevicePrivateData* m_pDevicePrivateData; - /* The number of bytes received so far (since last time this member was reset). */ - XnUInt32 m_nBytesReceived; - /* Stores last packet ID */ - XnUInt8 m_nLastPacketID; - /* The name of the stream. */ - const XnChar* m_csName; - -private: - /* Data used for calculating timestamps. */ - XnTimeStampData m_TimeStampData; -}; - -#endif //__XN_DATA_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DATA_PROCESSOR_H__ +#define __XN_DATA_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" +#include "XnDeviceSensorProtocol.h" +#include + +/** +* Base class for all data processors. +*/ +class XnDataProcessor +{ +public: + XnDataProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName); + virtual ~XnDataProcessor(); + +//--------------------------------------------------------------------------- +// Methods +//--------------------------------------------------------------------------- +public: + /** + * Initializes a Data Processor. + * + * @param pDevicePrivateData [in] A pointer to the device. + * @param csName [in] The name of the stream. + */ + virtual XnStatus Init(); + + /** + * Handles some data from this stream. + * + * @param pHeader [in] A pointer to current packet header. + * @param pData [in] A pointer to the data. + * @param nDataOffset [in] The offset of this data chunk inside current packet. + * @param nDataSize [in] Size of the data in bytes. + */ + void ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + +//--------------------------------------------------------------------------- +// Virtual Functions +//--------------------------------------------------------------------------- +protected: + virtual void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) = 0; + virtual void OnPacketLost(); + +//--------------------------------------------------------------------------- +// Utility Functions +//--------------------------------------------------------------------------- +protected: + /* + * Gets a calculated timestamp from the device timestamp. + * + * @param nDeviceTimeStamp [in] The device TS to translate. + */ + XnUInt64 GetTimeStamp(XnUInt32 nDeviceTimeStamp); + +//--------------------------------------------------------------------------- +// Class Members +//--------------------------------------------------------------------------- +protected: + XnDevicePrivateData* m_pDevicePrivateData; + /* The number of bytes received so far (since last time this member was reset). */ + XnUInt32 m_nBytesReceived; + /* Stores last packet ID */ + XnUInt8 m_nLastPacketID; + /* The name of the stream. */ + const XnChar* m_csName; + +private: + /* Data used for calculating timestamps. */ + XnTimeStampData m_TimeStampData; +}; + +#endif //__XN_DATA_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnDataProcessorHolder.cpp b/Source/XnDeviceSensorV2/XnDataProcessorHolder.cpp index 2da1dc6..750a9b1 100644 --- a/Source/XnDeviceSensorV2/XnDataProcessorHolder.cpp +++ b/Source/XnDeviceSensorV2/XnDataProcessorHolder.cpp @@ -1,100 +1,100 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessorHolder.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDataProcessorHolder::XnDataProcessorHolder() : - m_pProcessor(NULL), - m_hLock(NULL) -{ -} - -XnDataProcessorHolder::~XnDataProcessorHolder() -{ - xnOSCloseCriticalSection(&m_hLock); - XN_DELETE(m_pProcessor); -} - -XnStatus XnDataProcessorHolder::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSCreateCriticalSection(&m_hLock); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnDataProcessorHolder::Lock() -{ - xnOSEnterCriticalSection(&m_hLock); -} - -void XnDataProcessorHolder::Unlock() -{ - xnOSLeaveCriticalSection(&m_hLock); -} - -void XnDataProcessorHolder::Replace(XnDataProcessor* pNew) -{ - // lock first, to make sure processor is not in use right now - Lock(); - - if (m_pProcessor != NULL) - { - XN_DELETE(m_pProcessor); - } - - m_pProcessor = pNew; - - Unlock(); -} - -void XnDataProcessorHolder::ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - if (m_pProcessor == NULL) - return; - - // lock first - Lock(); - - // check again (it could have been replaced while we waited to lock) - if (m_pProcessor != NULL) - { - m_pProcessor->ProcessData(pHeader, pData, nDataOffset, nDataSize); - } - - Unlock(); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessorHolder.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDataProcessorHolder::XnDataProcessorHolder() : + m_pProcessor(NULL), + m_hLock(NULL) +{ +} + +XnDataProcessorHolder::~XnDataProcessorHolder() +{ + xnOSCloseCriticalSection(&m_hLock); + XN_DELETE(m_pProcessor); +} + +XnStatus XnDataProcessorHolder::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnDataProcessorHolder::Lock() +{ + xnOSEnterCriticalSection(&m_hLock); +} + +void XnDataProcessorHolder::Unlock() +{ + xnOSLeaveCriticalSection(&m_hLock); +} + +void XnDataProcessorHolder::Replace(XnDataProcessor* pNew) +{ + // lock first, to make sure processor is not in use right now + Lock(); + + if (m_pProcessor != NULL) + { + XN_DELETE(m_pProcessor); + } + + m_pProcessor = pNew; + + Unlock(); +} + +void XnDataProcessorHolder::ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + if (m_pProcessor == NULL) + return; + + // lock first + Lock(); + + // check again (it could have been replaced while we waited to lock) + if (m_pProcessor != NULL) + { + m_pProcessor->ProcessData(pHeader, pData, nDataOffset, nDataSize); + } + + Unlock(); +} + diff --git a/Source/XnDeviceSensorV2/XnDataProcessorHolder.h b/Source/XnDeviceSensorV2/XnDataProcessorHolder.h index fa7a03a..567e7bd 100644 --- a/Source/XnDeviceSensorV2/XnDataProcessorHolder.h +++ b/Source/XnDeviceSensorV2/XnDataProcessorHolder.h @@ -1,57 +1,57 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_PROCESSOR_HOLDER_H__ -#define __XN_STREAM_PROCESSOR_HOLDER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessor.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnDataProcessorHolder -{ -public: - XnDataProcessorHolder(); - ~XnDataProcessorHolder(); - - XnStatus Init(); - - void Replace(XnDataProcessor* pNew); - - void Lock(); - void Unlock(); - void ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - -private: - XN_CRITICAL_SECTION_HANDLE m_hLock; - XnDataProcessor* m_pProcessor; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_PROCESSOR_HOLDER_H__ +#define __XN_STREAM_PROCESSOR_HOLDER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessor.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnDataProcessorHolder +{ +public: + XnDataProcessorHolder(); + ~XnDataProcessorHolder(); + + XnStatus Init(); + + void Replace(XnDataProcessor* pNew); + + void Lock(); + void Unlock(); + void ProcessData(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + +private: + XN_CRITICAL_SECTION_HANDLE m_hLock; + XnDataProcessor* m_pProcessor; +}; + #endif //__XN_STREAM_PROCESSOR_HOLDER_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnDepthProcessor.cpp b/Source/XnDeviceSensorV2/XnDepthProcessor.cpp index 5b15c37..c11bde5 100644 --- a/Source/XnDeviceSensorV2/XnDepthProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnDepthProcessor.cpp @@ -1,196 +1,196 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDepthProcessor.h" -#include "XnSensor.h" -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnDepthProcessor::XnDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : - XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START, XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END), - m_pShiftToDepthTable(pStream->GetShiftToDepthTable()), - m_nPaddingPixelsOnEnd(0), - m_bShiftToDepthAllocated(FALSE) -{ -} - -XnDepthProcessor::~XnDepthProcessor() -{ - if (m_bShiftToDepthAllocated) - { - xnOSFree(m_pShiftToDepthTable); - } -} - -XnStatus XnDepthProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnFrameStreamProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - { - // optimization. We create a LUT shift-to-shift. See comment up. - m_pShiftToDepthTable = (XnDepthPixel*)xnOSMalloc(sizeof(XnDepthPixel)*XN_DEVICE_SENSOR_MAX_SHIFT_VALUE); - XN_VALIDATE_ALLOC_PTR(m_pShiftToDepthTable); - for (XnUInt32 i = 0; i < XN_DEVICE_SENSOR_MAX_SHIFT_VALUE; ++i) - { - m_pShiftToDepthTable[i] = i; - } - m_bShiftToDepthAllocated = TRUE; - } - break; - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_DEPTH, "Unknown Depth output: %d", GetStream()->GetOutputFormat()); - } - - return (XN_STATUS_OK); -} - -void XnDepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - // call base - XnFrameStreamProcessor::OnStartOfFrame(pHeader); - - if (m_pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1 && pHeader->nTimeStamp != 0) - { - // PATCH: starting with v5.1, the timestamp field of the SOF packet, is the number of pixels - // that should be prepended to the frame. - XnUInt32 nPaddingPixelsOnStart = pHeader->nTimeStamp >> 16; - m_nPaddingPixelsOnEnd = pHeader->nTimeStamp & 0x0000FFFF; - - PadPixels(nPaddingPixelsOnStart); - } -} - -XnUInt32 XnDepthProcessor::CalculateExpectedSize() -{ - XnUInt32 nExpectedDepthBufferSize = GetStream()->GetXRes() * GetStream()->GetYRes(); - - // when cropping is turned on, actual depth size is smaller - if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) - { - nExpectedDepthBufferSize = (XnUInt32)(GetStream()->m_FirmwareCropSizeX.GetValue() * GetStream()->m_FirmwareCropSizeY.GetValue()); - } - - nExpectedDepthBufferSize *= sizeof(XnDepthPixel); - - return nExpectedDepthBufferSize; -} - -void XnDepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - // pad pixels - if (m_nPaddingPixelsOnEnd != 0) - { - PadPixels(m_nPaddingPixelsOnEnd); - m_nPaddingPixelsOnEnd = 0 ; - } - - XnUInt32 nExpectedSize = CalculateExpectedSize(); - if (GetWriteBuffer()->GetSize() != nExpectedSize) - { - xnLogWarning(XN_MASK_SENSOR_READ, "Read: Depth buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedSize); - FrameIsCorrupted(); - } - - // call base - XnFrameStreamProcessor::OnEndOfFrame(pHeader); -} - -void XnDepthProcessor::PadPixels(XnUInt32 nPixels) -{ - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - // check for overflow - if (!CheckWriteBufferForOverflow(nPixels * sizeof(XnDepthPixel))) - { - return; - } - - XnDepthPixel* pWrite = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); - - // place the no-depth value - for (XnUInt32 i = 0; i < nPixels; ++i, ++pWrite) - *pWrite = GetStream()->GetNoDepthValue(); - - pWriteBuffer->UnsafeUpdateSize(nPixels * sizeof(XnDepthPixel)); -} - -void XnDepthProcessor::OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) -{ - XnFrameStreamProcessor::OnFrameReady(nFrameID, nFrameTS); - - m_pDevicePrivateData->pSensor->GetFPSCalculator()->MarkInputDepth(nFrameID, nFrameTS); -} - -void XnDepthProcessor::WriteShifts(XnUInt16* pShifts, XnUInt32 nCount) -{ - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - XnUInt32 nOutputSize = nCount * sizeof(XnDepthPixel); - - // make sure we have enough room - if (CheckWriteBufferForOverflow(nOutputSize)) - { - UnsafeWriteShifts(pShifts, nCount); - } -} - -void XnDepthProcessor::UnsafeWriteShifts(XnUInt16* pShifts, XnUInt32 nCount) -{ - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - XnDepthPixel* pWriteBuf = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); - XnUInt16* pRaw = pShifts; - XnUInt16* pRawEnd = pShifts + nCount; - - while (pRaw != pRawEnd) - { - *pWriteBuf = m_pShiftToDepthTable[*pRaw]; - ++pRaw; - ++pWriteBuf; - } - - pWriteBuffer->UnsafeUpdateSize(nCount * sizeof(XnDepthPixel)); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDepthProcessor.h" +#include "XnSensor.h" +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnDepthProcessor::XnDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : + XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START, XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END), + m_pShiftToDepthTable(pStream->GetShiftToDepthTable()), + m_nPaddingPixelsOnEnd(0), + m_bShiftToDepthAllocated(FALSE) +{ +} + +XnDepthProcessor::~XnDepthProcessor() +{ + if (m_bShiftToDepthAllocated) + { + xnOSFree(m_pShiftToDepthTable); + } +} + +XnStatus XnDepthProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnFrameStreamProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + { + // optimization. We create a LUT shift-to-shift. See comment up. + m_pShiftToDepthTable = (XnDepthPixel*)xnOSMalloc(sizeof(XnDepthPixel)*XN_DEVICE_SENSOR_MAX_SHIFT_VALUE); + XN_VALIDATE_ALLOC_PTR(m_pShiftToDepthTable); + for (XnUInt32 i = 0; i < XN_DEVICE_SENSOR_MAX_SHIFT_VALUE; ++i) + { + m_pShiftToDepthTable[i] = i; + } + m_bShiftToDepthAllocated = TRUE; + } + break; + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_DEPTH, "Unknown Depth output: %d", GetStream()->GetOutputFormat()); + } + + return (XN_STATUS_OK); +} + +void XnDepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + // call base + XnFrameStreamProcessor::OnStartOfFrame(pHeader); + + if (m_pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1 && pHeader->nTimeStamp != 0) + { + // PATCH: starting with v5.1, the timestamp field of the SOF packet, is the number of pixels + // that should be prepended to the frame. + XnUInt32 nPaddingPixelsOnStart = pHeader->nTimeStamp >> 16; + m_nPaddingPixelsOnEnd = pHeader->nTimeStamp & 0x0000FFFF; + + PadPixels(nPaddingPixelsOnStart); + } +} + +XnUInt32 XnDepthProcessor::CalculateExpectedSize() +{ + XnUInt32 nExpectedDepthBufferSize = GetStream()->GetXRes() * GetStream()->GetYRes(); + + // when cropping is turned on, actual depth size is smaller + if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) + { + nExpectedDepthBufferSize = (XnUInt32)(GetStream()->m_FirmwareCropSizeX.GetValue() * GetStream()->m_FirmwareCropSizeY.GetValue()); + } + + nExpectedDepthBufferSize *= sizeof(XnDepthPixel); + + return nExpectedDepthBufferSize; +} + +void XnDepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + // pad pixels + if (m_nPaddingPixelsOnEnd != 0) + { + PadPixels(m_nPaddingPixelsOnEnd); + m_nPaddingPixelsOnEnd = 0 ; + } + + XnUInt32 nExpectedSize = CalculateExpectedSize(); + if (GetWriteBuffer()->GetSize() != nExpectedSize) + { + xnLogWarning(XN_MASK_SENSOR_READ, "Read: Depth buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedSize); + FrameIsCorrupted(); + } + + // call base + XnFrameStreamProcessor::OnEndOfFrame(pHeader); +} + +void XnDepthProcessor::PadPixels(XnUInt32 nPixels) +{ + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + // check for overflow + if (!CheckWriteBufferForOverflow(nPixels * sizeof(XnDepthPixel))) + { + return; + } + + XnDepthPixel* pWrite = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); + + // place the no-depth value + for (XnUInt32 i = 0; i < nPixels; ++i, ++pWrite) + *pWrite = GetStream()->GetNoDepthValue(); + + pWriteBuffer->UnsafeUpdateSize(nPixels * sizeof(XnDepthPixel)); +} + +void XnDepthProcessor::OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) +{ + XnFrameStreamProcessor::OnFrameReady(nFrameID, nFrameTS); + + m_pDevicePrivateData->pSensor->GetFPSCalculator()->MarkInputDepth(nFrameID, nFrameTS); +} + +void XnDepthProcessor::WriteShifts(XnUInt16* pShifts, XnUInt32 nCount) +{ + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + XnUInt32 nOutputSize = nCount * sizeof(XnDepthPixel); + + // make sure we have enough room + if (CheckWriteBufferForOverflow(nOutputSize)) + { + UnsafeWriteShifts(pShifts, nCount); + } +} + +void XnDepthProcessor::UnsafeWriteShifts(XnUInt16* pShifts, XnUInt32 nCount) +{ + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + XnDepthPixel* pWriteBuf = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); + XnUInt16* pRaw = pShifts; + XnUInt16* pRawEnd = pShifts + nCount; + + while (pRaw != pRawEnd) + { + *pWriteBuf = m_pShiftToDepthTable[*pRaw]; + ++pRaw; + ++pWriteBuf; + } + + pWriteBuffer->UnsafeUpdateSize(nCount * sizeof(XnDepthPixel)); +} diff --git a/Source/XnDeviceSensorV2/XnDepthProcessor.h b/Source/XnDeviceSensorV2/XnDepthProcessor.h index 09ccd6b..eaec917 100644 --- a/Source/XnDeviceSensorV2/XnDepthProcessor.h +++ b/Source/XnDeviceSensorV2/XnDepthProcessor.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_DEPTH_PROCESSOR_H__ -#define __XN_DEPTH_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameStreamProcessor.h" -#include "XnSensorDepthStream.h" - -//--------------------------------------------------------------------------- -// Compilation Checks -//--------------------------------------------------------------------------- - -// Optimization: in order to save branches in the code itself, we create a shift-to-depth -// map which will actually translate shift-to-shift. This optimization relies on the -// fact that both shifts and depths are 16-bit long. If this is not the case, -// this optimization should be re-written. -// Then, any processor can always go through this LUT, no matter what the output format is. -#if (XnDepthPixel != XnUInt16) - #error "Depth and Shift do not have the same size. Need to reconsider optimization!" -#endif - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -class XnDepthProcessor : public XnFrameStreamProcessor -{ -public: - XnDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnDepthProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS); - - //--------------------------------------------------------------------------- - // Helper Functions - //--------------------------------------------------------------------------- - inline XnSensorDepthStream* GetStream() - { - return (XnSensorDepthStream*)XnFrameStreamProcessor::GetStream(); - } - - inline XnDepthPixel GetOutput(XnUInt16 nShift) - { - return m_pShiftToDepthTable[nShift]; - } - - void WriteShifts(XnUInt16* pShifts, XnUInt32 nCount); - void UnsafeWriteShifts(XnUInt16* pShifts, XnUInt32 nCount); - XnUInt32 CalculateExpectedSize(); - -private: - void PadPixels(XnUInt32 nPixels); - - XnUInt32 m_nPaddingPixelsOnEnd; - XnBool m_bShiftToDepthAllocated; - XnDepthPixel* m_pShiftToDepthTable; -}; - -#endif //__XN_DEPTH_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_DEPTH_PROCESSOR_H__ +#define __XN_DEPTH_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameStreamProcessor.h" +#include "XnSensorDepthStream.h" + +//--------------------------------------------------------------------------- +// Compilation Checks +//--------------------------------------------------------------------------- + +// Optimization: in order to save branches in the code itself, we create a shift-to-depth +// map which will actually translate shift-to-shift. This optimization relies on the +// fact that both shifts and depths are 16-bit long. If this is not the case, +// this optimization should be re-written. +// Then, any processor can always go through this LUT, no matter what the output format is. +#if (XnDepthPixel != XnUInt16) + #error "Depth and Shift do not have the same size. Need to reconsider optimization!" +#endif + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +class XnDepthProcessor : public XnFrameStreamProcessor +{ +public: + XnDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnDepthProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS); + + //--------------------------------------------------------------------------- + // Helper Functions + //--------------------------------------------------------------------------- + inline XnSensorDepthStream* GetStream() + { + return (XnSensorDepthStream*)XnFrameStreamProcessor::GetStream(); + } + + inline XnDepthPixel GetOutput(XnUInt16 nShift) + { + return m_pShiftToDepthTable[nShift]; + } + + void WriteShifts(XnUInt16* pShifts, XnUInt32 nCount); + void UnsafeWriteShifts(XnUInt16* pShifts, XnUInt32 nCount); + XnUInt32 CalculateExpectedSize(); + +private: + void PadPixels(XnUInt32 nPixels); + + XnUInt32 m_nPaddingPixelsOnEnd; + XnBool m_bShiftToDepthAllocated; + XnDepthPixel* m_pShiftToDepthTable; +}; + +#endif //__XN_DEPTH_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnDeviceSensor.cpp b/Source/XnDeviceSensorV2/XnDeviceSensor.cpp index 2f1fe5d..0e9c06a 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensor.cpp +++ b/Source/XnDeviceSensorV2/XnDeviceSensor.cpp @@ -1,124 +1,124 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnDeviceSensor.h" -#include "XnDeviceSensorInit.h" -#include "XnDeviceSensorIO.h" -#include "XnDeviceSensorProtocol.h" -#include -#include -#include "XnSensor.h" -#include "XnSensorClient.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -// Export XnDeviceSensor implementation for device interface -#define XN_DEVICE_BASE_DERIVATIVE XnDeviceSensor -#include - -// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! -XN_API_EXPORT_INIT() - -XnDeviceSensor::XnDeviceSensor() : XnDeviceBaseProxy(NULL) -{ - -} - -XnDeviceSensor::~XnDeviceSensor() -{ - -} - -XnStatus XnDeviceSensor::GetDefinition(XnDeviceDefinition* pDeviceDefinition) -{ - return XnSensor::GetDefinition(pDeviceDefinition); -} - -XnStatus XnDeviceSensor::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - return XnSensor::Enumerate(aConnectionStrings, pnCount); -} - -XnStatus XnDeviceSensor::Init(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pDeviceConfig); - - XnDeviceBase* pActualDevice = NULL; - - switch (pDeviceConfig->SharingMode) - { - case XN_DEVICE_EXCLUSIVE: - XN_VALIDATE_NEW(pActualDevice, XnSensor); - break; - case XN_DEVICE_SHARED: -#if (XN_PLATFORM != XN_PLATFORM_WIN32) - XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_INVALID_SHARING, XN_MASK_DEVICE_SENSOR, "Sensor sharing is only supported under win32!"); -#endif - XN_VALIDATE_NEW(pActualDevice, XnSensorClient); - break; - default: - return XN_STATUS_IO_DEVICE_INVALID_SHARING; - } - - // init actual device - nRetVal = pActualDevice->Init(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - ReplaceActualDevice(pActualDevice); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensor::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // destroy actual - nRetVal = XnDeviceBaseProxy::Destroy(); - XN_IS_STATUS_OK(nRetVal); - - IXnDevice* pActual = GetActual(); - - ReplaceActualDevice(NULL); - - XN_DELETE(pActual); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensor::DestroyStreamData(XnStreamData** ppStreamData) -{ - return XnSensor::DestroyStreamData(ppStreamData); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnDeviceSensor.h" +#include "XnDeviceSensorInit.h" +#include "XnDeviceSensorIO.h" +#include "XnDeviceSensorProtocol.h" +#include +#include +#include "XnSensor.h" +#include "XnSensorClient.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +// Export XnDeviceSensor implementation for device interface +#define XN_DEVICE_BASE_DERIVATIVE XnDeviceSensor +#include + +// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! +XN_API_EXPORT_INIT() + +XnDeviceSensor::XnDeviceSensor() : XnDeviceBaseProxy(NULL) +{ + +} + +XnDeviceSensor::~XnDeviceSensor() +{ + +} + +XnStatus XnDeviceSensor::GetDefinition(XnDeviceDefinition* pDeviceDefinition) +{ + return XnSensor::GetDefinition(pDeviceDefinition); +} + +XnStatus XnDeviceSensor::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + return XnSensor::Enumerate(aConnectionStrings, pnCount); +} + +XnStatus XnDeviceSensor::Init(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pDeviceConfig); + + XnDeviceBase* pActualDevice = NULL; + + switch (pDeviceConfig->SharingMode) + { + case XN_DEVICE_EXCLUSIVE: + XN_VALIDATE_NEW(pActualDevice, XnSensor); + break; + case XN_DEVICE_SHARED: +#if (XN_PLATFORM != XN_PLATFORM_WIN32) + XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_INVALID_SHARING, XN_MASK_DEVICE_SENSOR, "Sensor sharing is only supported under win32!"); +#endif + XN_VALIDATE_NEW(pActualDevice, XnSensorClient); + break; + default: + return XN_STATUS_IO_DEVICE_INVALID_SHARING; + } + + // init actual device + nRetVal = pActualDevice->Init(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + ReplaceActualDevice(pActualDevice); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensor::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // destroy actual + nRetVal = XnDeviceBaseProxy::Destroy(); + XN_IS_STATUS_OK(nRetVal); + + IXnDevice* pActual = GetActual(); + + ReplaceActualDevice(NULL); + + XN_DELETE(pActual); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensor::DestroyStreamData(XnStreamData** ppStreamData) +{ + return XnSensor::DestroyStreamData(ppStreamData); +} diff --git a/Source/XnDeviceSensorV2/XnDeviceSensor.h b/Source/XnDeviceSensorV2/XnDeviceSensor.h index 9c3a17d..2448426 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensor.h +++ b/Source/XnDeviceSensorV2/XnDeviceSensor.h @@ -1,602 +1,602 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_DEVICESENSOR_H_ -#define _XN_DEVICESENSOR_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#ifndef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS - #undef XN_DEVICE_EXPORT_PREFIX - #define XN_DEVICE_EXPORT_PREFIX SensorV2_ -#endif - -#include -#include -#include -#include "XnDeviceSensorIO.h" -#include -#include -#include -#include -#include -#include "XnSensorFPS.h" -#include "XnFirmwareInfo.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEVICE_MAJORVERSION 1 -#define XN_DEVICE_MINORVERSION 0 -#define XN_DEVICE_NAME "SensorV2" -#define XN_DEVICE_DESCRIPTION "Xiron I/O Prime Sensor v2/v3/v4 Device" - -#define XN_DEVICE_SENSOR_THREAD_KILL_TIMEOUT 5000 - -#define XN_DEVICE_SENSOR_DEPTH_CMOS_XRES 1280 -#define XN_DEVICE_SENSOR_DEPTH_CMOS_YRES 1024 - -#define XN_DEVICE_SENSOR_QVGA_DEPTH_XRES 320 -#define XN_DEVICE_SENSOR_QVGA_DEPTH_YRES 240 -#define XN_DEVICE_SENSOR_QVGA_DEPTH_YRES_COMPATIBLE 256 -#define XN_DEVICE_SENSOR_QVGA_IMAGE_XRES XN_DEVICE_SENSOR_QVGA_DEPTH_XRES -#define XN_DEVICE_SENSOR_QVGA_IMAGE_YRES XN_DEVICE_SENSOR_QVGA_DEPTH_YRES -#define XN_DEVICE_SENSOR_QVGA_IMAGE_YRES_COMPATIBLE XN_DEVICE_SENSOR_QVGA_DEPTH_YRES_COMPATIBLE - -#define XN_DEVICE_SENSOR_VGA_DEPTH_XRES 640 -#define XN_DEVICE_SENSOR_VGA_DEPTH_YRES 480 -#define XN_DEVICE_SENSOR_VGA_DEPTH_YRES_COMPATIBLE 512 -#define XN_DEVICE_SENSOR_VGA_IMAGE_XRES XN_DEVICE_SENSOR_VGA_DEPTH_XRES -#define XN_DEVICE_SENSOR_VGA_IMAGE_YRES XN_DEVICE_SENSOR_VGA_DEPTH_YRES -#define XN_DEVICE_SENSOR_VGA_IMAGE_YRES_COMPATIBLE XN_DEVICE_SENSOR_VGA_DEPTH_YRES_COMPATIBLE - -#define XN_DEVICE_SENSOR_SXGA_IMAGE_XRES 1280 -#define XN_DEVICE_SENSOR_SXGA_IMAGE_YRES 1024 - -#define XN_DEVICE_SENSOR_UXGA_IMAGE_XRES 1600 -#define XN_DEVICE_SENSOR_UXGA_IMAGE_YRES 1200 -/* -#define XN_DEVICE_SENSOR_HD720_IMAGE_XRES 1280 -#define XN_DEVICE_SENSOR_HD720_IMAGE_YRES 720 - -#define XN_DEVICE_SENSOR_2MPIX_IMAGE_XRES 1600 -#define XN_DEVICE_SENSOR_2MPIX_IMAGE_YRES 1200 -*/ -#define XN_DEVICE_SENSOR_MAX_IMAGE_XRES XN_DEVICE_SENSOR_SXGA_IMAGE_XRES -#define XN_DEVICE_SENSOR_MAX_IMAGE_YRES XN_DEVICE_SENSOR_SXGA_IMAGE_YRES - -#define XN_DEVICE_SENSOR_DEFAULT_DEPTH_XRES XN_DEVICE_SENSOR_QVGA_DEPTH_XRES -#define XN_DEVICE_SENSOR_DEFAULT_DEPTH_YRES XN_DEVICE_SENSOR_QVGA_DEPTH_YRES -#define XN_DEVICE_SENSOR_DEFAULT_IMAGE_XRES XN_DEVICE_SENSOR_QVGA_IMAGE_XRES -#define XN_DEVICE_SENSOR_DEFAULT_IMAGE_YRES XN_DEVICE_SENSOR_QVGA_IMAGE_YRES - -#define XN_DEVICE_SENSOR_INTERNAL_IMAGE_XRES XN_DEVICE_SENSOR_VGA_IMAGE_XRES -#define XN_DEVICE_SENSOR_INTERNAL_IMAGE_YRES XN_DEVICE_SENSOR_VGA_IMAGE_YRES - -#define XN_DEVICE_SENSOR_MIN_DEPTH 0 -#define XN_DEVICE_SENSOR_MAX_DEPTH 10000 -#define XN_DEVICE_SENSOR_NO_DEPTH_VALUE 0 -#define XN_DEVICE_SENSOR_MAX_SHIFT_VALUE 2048/*336*/ - -#define XN_DEVICE_SENSOR_BOARDID_SEP ":" -#define XN_DEVICE_SENSOR_DEFAULT_ID "*" - -#define XN_DEVICE_SENSOR_INI_FILE_EXT ".ini" - -#define XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH 16 - -#define XN_SENSOR_PROFANE_DIST_QVGA 1 -#define XN_SENSOR_PROFANE_DIST_VGA 3 -#define XN_SENSOR_PROFANE_MDIFF 350 - -#define XN_SENSOR_GLOBHIST_REGSIZE_QVGA 40 -#define XN_SENSOR_GLOBHIST_REGSIZESCORE_QVGA 62 -#define XN_SENSOR_GLOBHIST_FRAME_SIZE_QVGA 7 - -#define XN_SENSOR_GLOBHIST_REGSIZE_VGA 160 -#define XN_SENSOR_GLOBHIST_REGSIZESCORE_VGA 250 -#define XN_SENSOR_GLOBHIST_FRAME_SIZE_VGA 15 - -#define XN_SENSOR_PP_FILTER_HEIGHT_SPACE_QVGA 4 -#define XN_SENSOR_PP_FILTER_HEIGHT_SPACE_VGA 8 - -#define XN_SENSOR_PROTOCOL_NUM_FRAME_BUFFERS 3 - -#define XN_SENSOR_TIMESTAMP_SANITY_DIFF 10 // in ms - -#define XN_MASK_DEVICE_SENSOR "DeviceSensor" -#define XN_MASK_DEVICE_IO "DeviceIO" -#define XN_MASK_SENSOR_PROTOCOL "DeviceSensorProtocol" -#define XN_MASK_SENSOR_PROTOCOL_IMAGE XN_MASK_SENSOR_PROTOCOL "Image" -#define XN_MASK_SENSOR_PROTOCOL_DEPTH XN_MASK_SENSOR_PROTOCOL "Depth" -#define XN_MASK_SENSOR_PROTOCOL_AUDIO XN_MASK_SENSOR_PROTOCOL "Audio" -#define XN_MASK_SENSOR_READ "DeviceSensorRead" -#define XN_MASK_SENSOR_READ_IMAGE XN_MASK_SENSOR_READ "Image" -#define XN_MASK_SENSOR_READ_DEPTH XN_MASK_SENSOR_READ "Depth" -#define XN_MASK_SENSOR_READ_AUDIO XN_MASK_SENSOR_READ "Audio" -#define XN_DUMP_AUDIO_IN "AudioIn" -#define XN_DUMP_IMAGE_IN "ImageIn" -#define XN_DUMP_DEPTH_IN "DepthIn" -#define XN_DUMP_MINI_PACKETS "MiniPackets" -#define XN_DUMP_TIMESTAMPS "SensorTimestamps" -#define XN_DUMP_BANDWIDTH "SensorBandwidth" -#define XN_DUMP_BAD_IMAGE "BadImage" -#define XN_DUMP_FRAME_SYNC "FrameSync" - - -#define XN_NORMALIZE_DEPTH(x) XN_MAX(XN_MIN(x, XN_DEVICE_SENSOR_MAX_DEPTH), XN_DEVICE_SENSOR_MIN_DEPTH) - -//--------------------------------------------------------------------------- -// Forward Declarations -//--------------------------------------------------------------------------- -class XnSensorFirmware; -struct XnDevicePrivateData; -class XnSensorFixedParams; -class XnSensorFPS; -class XnCmosInfo; - -//--------------------------------------------------------------------------- -// Structures & Enums -//--------------------------------------------------------------------------- - -typedef struct XnSensorObjects -{ - XnSensorObjects(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData, XnSensorFixedParams* pFixedParams, XnSensorFPS* pFPS, XnCmosInfo* pCmosInfo) : - pFirmware(pFirmware), - pDevicePrivateData(pDevicePrivateData), - pFixedParams(pFixedParams), - pFPS(pFPS), - pCmosInfo(pCmosInfo) - {} - - XnSensorFirmware* pFirmware; - XnDevicePrivateData* pDevicePrivateData; - XnSensorFixedParams* pFixedParams; - XnSensorFPS* pFPS; - XnCmosInfo* pCmosInfo; -} XnSensorObjects; - -typedef struct XnSensorInfo -{ - XnSensorVer nSensorVer; -// XnChar cSensorID[XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH+1]; -} XnSensorInfo; - -typedef struct XnHWInfo -{ - XnHWVer nHWVer; -} XnHWInfo; - -typedef struct XnChipInfo -{ - XnChipVer nChipVer; -} XnChipInfo; - -typedef enum { - RGBREG_NONE = 0, - RGBREG_FIX_IMAGE = 1, - RGBREG_FIX_DEPTH = 2 -} XnDeviceSensorRGBRegType; - -typedef struct -{ - XN_THREAD_HANDLE hThread; - XnBool bKillThread; - XnBool bThreadAlive; -} XnDeviceSensorThreadContext; - -typedef struct XnRegistrationFunctionCoefficients -{ - XnDouble dA; - XnDouble dB; - XnDouble dC; - XnDouble dD; - XnDouble dE; - XnDouble dF; -} XnRegistrationFunctionCoefficients; - -typedef struct -{ - /* Is this the first time timestamp is calculated. */ - XnBool bFirst; - /* The device TS which we use as reference for calculation. */ - XnUInt32 nReferenceTS; - /* The time corresponding to the TS in nReferenceTS. */ - XnUInt64 nTotalTicksAtReferenceTS; - /* The last device TS received. */ - XnUInt32 nLastDeviceTS; - /* The last result time calculated. */ - XnUInt64 nLastResultTime; - /* Stream name - for debug purposes. */ - const XnChar* csStreamName; -} XnTimeStampData; - - -typedef struct XnCmosBlankingCoefficients -{ - XnFloat fA; - XnFloat fB; -} XnCmosBlankingCoefficients; - -typedef struct XnCmosBlankingInformation -{ - XnCmosBlankingCoefficients Coefficients[2]; -} XnCmosBlankingInformation; - -typedef XnStatus (XN_CALLBACK_TYPE* NewAudioDataCallback)(void* pCookie); - -struct XnSpecificUsbDevice; // Forward Declaration -class XnSensor; // Forward Declaration - -typedef struct XnDevicePrivateData -{ - XnVersions Version; - XnUInt32 nDepthFramePos; - XnUInt32 nImageFramePos; - - XnChar cpSensorID[XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH+1]; - XnUInt8 nBoardID; - XN_SENSOR_HANDLE SensorHandle; - XnSensorInfo SensorInfo; - XnFirmwareInfo FWInfo; - XnHWInfo HWInfo; - XnChipInfo ChipInfo; - - XN_CRITICAL_SECTION_HANDLE hAudioBufferCriticalSection; - - XnSpecificUsbDevice* pSpecificDepthUsb; - XnSpecificUsbDevice* pSpecificImageUsb; - XnSpecificUsbDevice* pSpecificMiscUsb; - - XnUInt32 nImageBayerDownSampleStep; - - XnCropping IRCropping; - - /** A single (big) buffer for audio. */ - XN_AUDIO_TYPE* pAudioBuffer; - /** An array of pointers into the audio buffer. */ - XnUInt64* pAudioPacketsTimestamps; - /** The index of the next packet that should be written. */ - volatile XnUInt32 nAudioWriteIndex; - /** The index of the next packet that can be read. */ - volatile XnUInt32 nAudioReadIndex; - /** Size of the audio buffer, in packets. */ - XnUInt32 nAudioBufferNumOfPackets; - /** Size of the audio buffer, in bytes. */ - XnUInt32 nAudioBufferSize; - XnUInt32 nAudioPacketSize; - /** When true, when reading from device, if frames were lost, their audio will also be dropped. */ - XnBool bSyncAudio; - /** A callback for new data */ - NewAudioDataCallback pAudioCallback; - void* pAudioCallbackCookie; - - XnFloat fDeviceFrequency; - - /** Keeps the global reference TS (the one marking time-zero). */ - XnUInt32 nGlobalReferenceTS; - /** Keeps the OS time of global reference TS. */ - XnUInt64 nGlobalReferenceOSTime; - - /** A general critical section used to synch end-points threads. */ - XN_CRITICAL_SECTION_HANDLE hEndPointsCS; - - XnDepthPixel* pTempDepth1; - XnUInt8* pTempImage1; - - XnDeviceConfig DeviceConfig; - - XnBool bIgnoreDataPackets; - - XnUInt16 nFrameSync; - - /** Used to dump timestamps data. */ - XnDump TimestampsDump; - /** Used to dump bandwidth data. */ - XnDump BandwidthDump; - /** Used to dump MiniPackets data. */ - XnDump MiniPacketsDump; - - XnBool bDepthMirror; - XnBool bImageMirror; - XnBool bIRMirror; - - XnBool bMirror; // Mirroring is ON - - XnSensor* pSensor; - - XN_MUTEX_HANDLE hExecuteMutex; - - -} XnDevicePrivateData; - -#pragma pack (push, 1) - -typedef struct XnFixedParams -{ - // Misc - XnInt32 nSerialNumber; - XnInt32 nWatchDogTimeout; - - // Flash - XnInt32 nFlashType; - XnInt32 nFlashSize; - XnInt32 nFlashBurstEnable; - XnInt32 nFmifReadBurstCycles; - XnInt32 nFmifReadAccessCycles; - XnInt32 nFmifReadRecoverCycles; - XnInt32 nFmifWriteAccessCycles; - XnInt32 nFmifWriteRecoverCycles; - XnInt32 nFmifWriteAssertionCycles; - - // Audio - XnInt32 nI2SLogicClockPolarity; - - // Depth - XnInt32 nDepthCiuHorizontalSyncPolarity; - XnInt32 nDepthCiuVerticalSyncPolarity; - XnInt32 nDepthCmosType; - XnInt32 nDepthCmosI2CAddress; - XnInt32 nDepthCmosI2CBus; - - // Image - XnInt32 nImageCiuHorizontalSyncPolarity; - XnInt32 nImageCiuVerticalSyncPolarity; - XnInt32 nImageCmosType; - XnInt32 nImageCmosI2CAddress; - XnInt32 nImageCmosI2CBus; - - // Geometry - XnInt32 nIrCmosCloseToProjector; - XnFloat fDCmosEmitterDistance; - XnFloat fDCmosRCmosDistance; - XnFloat fReferenceDistance; - XnFloat fReferencePixelSize; - - // Clocks - XnInt32 nPllValue; - XnInt32 nSystemClockDivider; - XnInt32 nRCmosClockDivider; - XnInt32 nDCmosClockDivider; - XnInt32 nAdcClocDivider; - XnInt32 nI2CStandardSpeedHCount; - XnInt32 nI2CStandardSpeedLCount; - - XnInt32 nI2CHoldFixDelay; - - XnInt32 nSensorType; - XnInt32 nDebugMode; - XnInt32 nUseExtPhy; - XnInt32 bProjectorProtectionEnabled; - XnInt32 nProjectorDACOutputVoltage; - XnInt32 nProjectorDACOutputVoltage2; - XnInt32 nTecEmitterDelay; -} XnFixedParams; - -typedef struct XnFixedParamsV26 -{ - // Misc - XnInt32 nSerialNumber; - XnInt32 nWatchDogTimeout; - - // Flash - XnInt32 nFlashType; - XnInt32 nFlashSize; - XnInt32 nFlashBurstEnable; - XnInt32 nFmifReadBurstCycles; - XnInt32 nFmifReadAccessCycles; - XnInt32 nFmifReadRecoverCycles; - XnInt32 nFmifWriteAccessCycles; - XnInt32 nFmifWriteRecoverCycles; - XnInt32 nFmifWriteAssertionCycles; - - // Audio - XnInt32 nI2SLogicClockPolarity; - - // Depth - XnInt32 nDepthCiuHorizontalSyncPolarity; - XnInt32 nDepthCiuVerticalSyncPolarity; - XnInt32 nDepthCmosType; - XnInt32 nDepthCmosI2CAddress; - XnInt32 nDepthCmosI2CBus; - - // Image - XnInt32 nImageCiuHorizontalSyncPolarity; - XnInt32 nImageCiuVerticalSyncPolarity; - XnInt32 nImageCmosType; - XnInt32 nImageCmosI2CAddress; - XnInt32 nImageCmosI2CBus; - - // Geometry - XnInt32 nIrCmosCloseToProjector; - XnFloat fDCmosEmitterDistance; - XnFloat fDCmosRCmosDistance; - XnFloat fReferenceDistance; - XnFloat fReferencePixelSize; - - // Clocks - XnInt32 nPllValue; - XnInt32 nSystemClockDivider; - XnInt32 nRCmosClockDivider; - XnInt32 nDCmosClockDivider; - XnInt32 nAdcClocDivider; - XnInt32 nI2CStandardSpeedHCount; - XnInt32 nI2CStandardSpeedLCount; - - XnInt32 nI2CHoldFixDelay; - - XnInt32 nSensorType; - XnInt32 nDebugMode; - XnInt32 nTecEmitterDelay; - XnInt32 nUseExtPhy; -} XnFixedParamsV26; - -typedef struct XnFixedParamsV20 -{ - // Misc - XnInt32 nSerialNumber; - XnInt32 nWatchDogTimeout; - - // Flash - XnInt32 nFlashType; - XnInt32 nFlashSize; - XnInt32 nFlashBurstEnable; - XnInt32 nFmifReadBurstCycles; - XnInt32 nFmifReadAccessCycles; - XnInt32 nFmifReadRecoverCycles; - XnInt32 nFmifWriteAccessCycles; - XnInt32 nFmifWriteRecoverCycles; - XnInt32 nFmifWriteAssertionCycles; - - // Audio - XnInt32 nI2SLogicClockPolarity; - - // Depth - XnInt32 nDepthCiuHorizontalSyncPolarity; - XnInt32 nDepthCiuVerticalSyncPolarity; - XnInt32 nDepthCmosType; - XnInt32 nDepthCmosI2CAddress; - XnInt32 nDepthCmosI2CBus; - - // Image - XnInt32 nImageCiuHorizontalSyncPolarity; - XnInt32 nImageCiuVerticalSyncPolarity; - XnInt32 nImageCmosType; - XnInt32 nImageCmosI2CAddress; - XnInt32 nImageCmosI2CBus; - - // Geometry - XnInt32 nIrCmosCloseToProjector; - XnFloat fDCmosEmitterDistance; - XnFloat fDCmosRCmosDistance; - XnFloat fReferenceDistance; - XnFloat fReferencePixelSize; - - // Clocks - XnInt32 nPllValue; - XnInt32 nSystemClockDivider; - XnInt32 nRCmosClockDivider; - XnInt32 nDCmosClockDivider; - XnInt32 nAdcClocDivider; - XnInt32 nI2CStandardSpeedHCount; - XnInt32 nI2CStandardSpeedLCount; - - XnInt32 nI2CHoldFixDelay; - - XnInt32 nSensorType; - XnInt32 nDebugMode; - XnInt32 nTecEmitterDelay; -} XnFixedParamsV20; - -typedef struct XnRegistrationInformation1000 -{ - XnRegistrationFunctionCoefficients FuncX; - XnRegistrationFunctionCoefficients FuncY; - XnDouble dBeta; -} XnRegistrationInformation1000; - -typedef struct XnRegistrationInformation1080 -{ - XnInt32 nRGS_DX_CENTER; - XnInt32 nRGS_AX; - XnInt32 nRGS_BX; - XnInt32 nRGS_CX; - XnInt32 nRGS_DX; - XnInt32 nRGS_DX_START; - XnInt32 nRGS_AY; - XnInt32 nRGS_BY; - XnInt32 nRGS_CY; - XnInt32 nRGS_DY; - XnInt32 nRGS_DY_START; - XnInt32 nRGS_DX_BETA_START; - XnInt32 nRGS_DY_BETA_START; - XnInt32 nRGS_ROLLOUT_BLANK; - XnInt32 nRGS_ROLLOUT_SIZE; - XnInt32 nRGS_DX_BETA_INC; - XnInt32 nRGS_DY_BETA_INC; - XnInt32 nRGS_DXDX_START; - XnInt32 nRGS_DXDY_START; - XnInt32 nRGS_DYDX_START; - XnInt32 nRGS_DYDY_START; - XnInt32 nRGS_DXDXDX_START; - XnInt32 nRGS_DYDXDX_START; - XnInt32 nRGS_DXDXDY_START; - XnInt32 nRGS_DYDXDY_START; - XnInt32 nBACK_COMP1; - XnInt32 nRGS_DYDYDX_START; - XnInt32 nBACK_COMP2; - XnInt32 nRGS_DYDYDY_START; -} XnRegistrationInformation1080; - -typedef struct XnRegistrationPaddingInformation -{ - XnUInt16 nStartLines; - XnUInt16 nEndLines; - XnUInt16 nCroppingLines; -} XnRegistrationPaddingInformation; - -typedef struct XnDepthInformation -{ - XnUInt16 nConstShift; -} XnDepthInformation; - -typedef struct XnFrequencyInformation -{ - XnFloat fDeviceFrequency; -} XnFrequencyInformation; - -typedef struct XnAudioSharedBuffer -{ - XnUInt32 nPacketCount; - XnUInt32 nPacketSize; - XnUInt32 nTimestampsListOffset; - XnUInt32 nBufferOffset; - XnUInt32 nWritePacketIndex; -} XnAudioSharedBuffer; - -#pragma pack (pop) - -class XnDeviceSensor : public XnDeviceBaseProxy -{ -public: - XnDeviceSensor(); - ~XnDeviceSensor(); - - static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); - static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); - - virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus Destroy(); - - static XnStatus DestroyStreamData(XnStreamData** ppStreamData); -}; - -XnStatus XnDeviceSensorSetParam(XnDevicePrivateData* pDevicePrivateData, const XnChar* cpParamName, const XnInt32 nValue); - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_DEVICESENSOR_H_ +#define _XN_DEVICESENSOR_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#ifndef XN_PLATFORM_SUPPORTS_DYNAMIC_LIBS + #undef XN_DEVICE_EXPORT_PREFIX + #define XN_DEVICE_EXPORT_PREFIX SensorV2_ +#endif + +#include +#include +#include +#include "XnDeviceSensorIO.h" +#include +#include +#include +#include +#include +#include "XnSensorFPS.h" +#include "XnFirmwareInfo.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEVICE_MAJORVERSION 1 +#define XN_DEVICE_MINORVERSION 0 +#define XN_DEVICE_NAME "SensorV2" +#define XN_DEVICE_DESCRIPTION "Xiron I/O Prime Sensor v2/v3/v4 Device" + +#define XN_DEVICE_SENSOR_THREAD_KILL_TIMEOUT 5000 + +#define XN_DEVICE_SENSOR_DEPTH_CMOS_XRES 1280 +#define XN_DEVICE_SENSOR_DEPTH_CMOS_YRES 1024 + +#define XN_DEVICE_SENSOR_QVGA_DEPTH_XRES 320 +#define XN_DEVICE_SENSOR_QVGA_DEPTH_YRES 240 +#define XN_DEVICE_SENSOR_QVGA_DEPTH_YRES_COMPATIBLE 256 +#define XN_DEVICE_SENSOR_QVGA_IMAGE_XRES XN_DEVICE_SENSOR_QVGA_DEPTH_XRES +#define XN_DEVICE_SENSOR_QVGA_IMAGE_YRES XN_DEVICE_SENSOR_QVGA_DEPTH_YRES +#define XN_DEVICE_SENSOR_QVGA_IMAGE_YRES_COMPATIBLE XN_DEVICE_SENSOR_QVGA_DEPTH_YRES_COMPATIBLE + +#define XN_DEVICE_SENSOR_VGA_DEPTH_XRES 640 +#define XN_DEVICE_SENSOR_VGA_DEPTH_YRES 480 +#define XN_DEVICE_SENSOR_VGA_DEPTH_YRES_COMPATIBLE 512 +#define XN_DEVICE_SENSOR_VGA_IMAGE_XRES XN_DEVICE_SENSOR_VGA_DEPTH_XRES +#define XN_DEVICE_SENSOR_VGA_IMAGE_YRES XN_DEVICE_SENSOR_VGA_DEPTH_YRES +#define XN_DEVICE_SENSOR_VGA_IMAGE_YRES_COMPATIBLE XN_DEVICE_SENSOR_VGA_DEPTH_YRES_COMPATIBLE + +#define XN_DEVICE_SENSOR_SXGA_IMAGE_XRES 1280 +#define XN_DEVICE_SENSOR_SXGA_IMAGE_YRES 1024 + +#define XN_DEVICE_SENSOR_UXGA_IMAGE_XRES 1600 +#define XN_DEVICE_SENSOR_UXGA_IMAGE_YRES 1200 +/* +#define XN_DEVICE_SENSOR_HD720_IMAGE_XRES 1280 +#define XN_DEVICE_SENSOR_HD720_IMAGE_YRES 720 + +#define XN_DEVICE_SENSOR_2MPIX_IMAGE_XRES 1600 +#define XN_DEVICE_SENSOR_2MPIX_IMAGE_YRES 1200 +*/ +#define XN_DEVICE_SENSOR_MAX_IMAGE_XRES XN_DEVICE_SENSOR_SXGA_IMAGE_XRES +#define XN_DEVICE_SENSOR_MAX_IMAGE_YRES XN_DEVICE_SENSOR_SXGA_IMAGE_YRES + +#define XN_DEVICE_SENSOR_DEFAULT_DEPTH_XRES XN_DEVICE_SENSOR_QVGA_DEPTH_XRES +#define XN_DEVICE_SENSOR_DEFAULT_DEPTH_YRES XN_DEVICE_SENSOR_QVGA_DEPTH_YRES +#define XN_DEVICE_SENSOR_DEFAULT_IMAGE_XRES XN_DEVICE_SENSOR_QVGA_IMAGE_XRES +#define XN_DEVICE_SENSOR_DEFAULT_IMAGE_YRES XN_DEVICE_SENSOR_QVGA_IMAGE_YRES + +#define XN_DEVICE_SENSOR_INTERNAL_IMAGE_XRES XN_DEVICE_SENSOR_VGA_IMAGE_XRES +#define XN_DEVICE_SENSOR_INTERNAL_IMAGE_YRES XN_DEVICE_SENSOR_VGA_IMAGE_YRES + +#define XN_DEVICE_SENSOR_MIN_DEPTH 0 +#define XN_DEVICE_SENSOR_MAX_DEPTH 10000 +#define XN_DEVICE_SENSOR_NO_DEPTH_VALUE 0 +#define XN_DEVICE_SENSOR_MAX_SHIFT_VALUE 2048/*336*/ + +#define XN_DEVICE_SENSOR_BOARDID_SEP ":" +#define XN_DEVICE_SENSOR_DEFAULT_ID "*" + +#define XN_DEVICE_SENSOR_INI_FILE_EXT ".ini" + +#define XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH 16 + +#define XN_SENSOR_PROFANE_DIST_QVGA 1 +#define XN_SENSOR_PROFANE_DIST_VGA 3 +#define XN_SENSOR_PROFANE_MDIFF 350 + +#define XN_SENSOR_GLOBHIST_REGSIZE_QVGA 40 +#define XN_SENSOR_GLOBHIST_REGSIZESCORE_QVGA 62 +#define XN_SENSOR_GLOBHIST_FRAME_SIZE_QVGA 7 + +#define XN_SENSOR_GLOBHIST_REGSIZE_VGA 160 +#define XN_SENSOR_GLOBHIST_REGSIZESCORE_VGA 250 +#define XN_SENSOR_GLOBHIST_FRAME_SIZE_VGA 15 + +#define XN_SENSOR_PP_FILTER_HEIGHT_SPACE_QVGA 4 +#define XN_SENSOR_PP_FILTER_HEIGHT_SPACE_VGA 8 + +#define XN_SENSOR_PROTOCOL_NUM_FRAME_BUFFERS 3 + +#define XN_SENSOR_TIMESTAMP_SANITY_DIFF 10 // in ms + +#define XN_MASK_DEVICE_SENSOR "DeviceSensor" +#define XN_MASK_DEVICE_IO "DeviceIO" +#define XN_MASK_SENSOR_PROTOCOL "DeviceSensorProtocol" +#define XN_MASK_SENSOR_PROTOCOL_IMAGE XN_MASK_SENSOR_PROTOCOL "Image" +#define XN_MASK_SENSOR_PROTOCOL_DEPTH XN_MASK_SENSOR_PROTOCOL "Depth" +#define XN_MASK_SENSOR_PROTOCOL_AUDIO XN_MASK_SENSOR_PROTOCOL "Audio" +#define XN_MASK_SENSOR_READ "DeviceSensorRead" +#define XN_MASK_SENSOR_READ_IMAGE XN_MASK_SENSOR_READ "Image" +#define XN_MASK_SENSOR_READ_DEPTH XN_MASK_SENSOR_READ "Depth" +#define XN_MASK_SENSOR_READ_AUDIO XN_MASK_SENSOR_READ "Audio" +#define XN_DUMP_AUDIO_IN "AudioIn" +#define XN_DUMP_IMAGE_IN "ImageIn" +#define XN_DUMP_DEPTH_IN "DepthIn" +#define XN_DUMP_MINI_PACKETS "MiniPackets" +#define XN_DUMP_TIMESTAMPS "SensorTimestamps" +#define XN_DUMP_BANDWIDTH "SensorBandwidth" +#define XN_DUMP_BAD_IMAGE "BadImage" +#define XN_DUMP_FRAME_SYNC "FrameSync" + + +#define XN_NORMALIZE_DEPTH(x) XN_MAX(XN_MIN(x, XN_DEVICE_SENSOR_MAX_DEPTH), XN_DEVICE_SENSOR_MIN_DEPTH) + +//--------------------------------------------------------------------------- +// Forward Declarations +//--------------------------------------------------------------------------- +class XnSensorFirmware; +struct XnDevicePrivateData; +class XnSensorFixedParams; +class XnSensorFPS; +class XnCmosInfo; + +//--------------------------------------------------------------------------- +// Structures & Enums +//--------------------------------------------------------------------------- + +typedef struct XnSensorObjects +{ + XnSensorObjects(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData, XnSensorFixedParams* pFixedParams, XnSensorFPS* pFPS, XnCmosInfo* pCmosInfo) : + pFirmware(pFirmware), + pDevicePrivateData(pDevicePrivateData), + pFixedParams(pFixedParams), + pFPS(pFPS), + pCmosInfo(pCmosInfo) + {} + + XnSensorFirmware* pFirmware; + XnDevicePrivateData* pDevicePrivateData; + XnSensorFixedParams* pFixedParams; + XnSensorFPS* pFPS; + XnCmosInfo* pCmosInfo; +} XnSensorObjects; + +typedef struct XnSensorInfo +{ + XnSensorVer nSensorVer; +// XnChar cSensorID[XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH+1]; +} XnSensorInfo; + +typedef struct XnHWInfo +{ + XnHWVer nHWVer; +} XnHWInfo; + +typedef struct XnChipInfo +{ + XnChipVer nChipVer; +} XnChipInfo; + +typedef enum { + RGBREG_NONE = 0, + RGBREG_FIX_IMAGE = 1, + RGBREG_FIX_DEPTH = 2 +} XnDeviceSensorRGBRegType; + +typedef struct +{ + XN_THREAD_HANDLE hThread; + XnBool bKillThread; + XnBool bThreadAlive; +} XnDeviceSensorThreadContext; + +typedef struct XnRegistrationFunctionCoefficients +{ + XnDouble dA; + XnDouble dB; + XnDouble dC; + XnDouble dD; + XnDouble dE; + XnDouble dF; +} XnRegistrationFunctionCoefficients; + +typedef struct +{ + /* Is this the first time timestamp is calculated. */ + XnBool bFirst; + /* The device TS which we use as reference for calculation. */ + XnUInt32 nReferenceTS; + /* The time corresponding to the TS in nReferenceTS. */ + XnUInt64 nTotalTicksAtReferenceTS; + /* The last device TS received. */ + XnUInt32 nLastDeviceTS; + /* The last result time calculated. */ + XnUInt64 nLastResultTime; + /* Stream name - for debug purposes. */ + const XnChar* csStreamName; +} XnTimeStampData; + + +typedef struct XnCmosBlankingCoefficients +{ + XnFloat fA; + XnFloat fB; +} XnCmosBlankingCoefficients; + +typedef struct XnCmosBlankingInformation +{ + XnCmosBlankingCoefficients Coefficients[2]; +} XnCmosBlankingInformation; + +typedef XnStatus (XN_CALLBACK_TYPE* NewAudioDataCallback)(void* pCookie); + +struct XnSpecificUsbDevice; // Forward Declaration +class XnSensor; // Forward Declaration + +typedef struct XnDevicePrivateData +{ + XnVersions Version; + XnUInt32 nDepthFramePos; + XnUInt32 nImageFramePos; + + XnChar cpSensorID[XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH+1]; + XnUInt8 nBoardID; + XN_SENSOR_HANDLE SensorHandle; + XnSensorInfo SensorInfo; + XnFirmwareInfo FWInfo; + XnHWInfo HWInfo; + XnChipInfo ChipInfo; + + XN_CRITICAL_SECTION_HANDLE hAudioBufferCriticalSection; + + XnSpecificUsbDevice* pSpecificDepthUsb; + XnSpecificUsbDevice* pSpecificImageUsb; + XnSpecificUsbDevice* pSpecificMiscUsb; + + XnUInt32 nImageBayerDownSampleStep; + + XnCropping IRCropping; + + /** A single (big) buffer for audio. */ + XN_AUDIO_TYPE* pAudioBuffer; + /** An array of pointers into the audio buffer. */ + XnUInt64* pAudioPacketsTimestamps; + /** The index of the next packet that should be written. */ + volatile XnUInt32 nAudioWriteIndex; + /** The index of the next packet that can be read. */ + volatile XnUInt32 nAudioReadIndex; + /** Size of the audio buffer, in packets. */ + XnUInt32 nAudioBufferNumOfPackets; + /** Size of the audio buffer, in bytes. */ + XnUInt32 nAudioBufferSize; + XnUInt32 nAudioPacketSize; + /** When true, when reading from device, if frames were lost, their audio will also be dropped. */ + XnBool bSyncAudio; + /** A callback for new data */ + NewAudioDataCallback pAudioCallback; + void* pAudioCallbackCookie; + + XnFloat fDeviceFrequency; + + /** Keeps the global reference TS (the one marking time-zero). */ + XnUInt32 nGlobalReferenceTS; + /** Keeps the OS time of global reference TS. */ + XnUInt64 nGlobalReferenceOSTime; + + /** A general critical section used to synch end-points threads. */ + XN_CRITICAL_SECTION_HANDLE hEndPointsCS; + + XnDepthPixel* pTempDepth1; + XnUInt8* pTempImage1; + + XnDeviceConfig DeviceConfig; + + XnBool bIgnoreDataPackets; + + XnUInt16 nFrameSync; + + /** Used to dump timestamps data. */ + XnDump TimestampsDump; + /** Used to dump bandwidth data. */ + XnDump BandwidthDump; + /** Used to dump MiniPackets data. */ + XnDump MiniPacketsDump; + + XnBool bDepthMirror; + XnBool bImageMirror; + XnBool bIRMirror; + + XnBool bMirror; // Mirroring is ON + + XnSensor* pSensor; + + XN_MUTEX_HANDLE hExecuteMutex; + + +} XnDevicePrivateData; + +#pragma pack (push, 1) + +typedef struct XnFixedParams +{ + // Misc + XnInt32 nSerialNumber; + XnInt32 nWatchDogTimeout; + + // Flash + XnInt32 nFlashType; + XnInt32 nFlashSize; + XnInt32 nFlashBurstEnable; + XnInt32 nFmifReadBurstCycles; + XnInt32 nFmifReadAccessCycles; + XnInt32 nFmifReadRecoverCycles; + XnInt32 nFmifWriteAccessCycles; + XnInt32 nFmifWriteRecoverCycles; + XnInt32 nFmifWriteAssertionCycles; + + // Audio + XnInt32 nI2SLogicClockPolarity; + + // Depth + XnInt32 nDepthCiuHorizontalSyncPolarity; + XnInt32 nDepthCiuVerticalSyncPolarity; + XnInt32 nDepthCmosType; + XnInt32 nDepthCmosI2CAddress; + XnInt32 nDepthCmosI2CBus; + + // Image + XnInt32 nImageCiuHorizontalSyncPolarity; + XnInt32 nImageCiuVerticalSyncPolarity; + XnInt32 nImageCmosType; + XnInt32 nImageCmosI2CAddress; + XnInt32 nImageCmosI2CBus; + + // Geometry + XnInt32 nIrCmosCloseToProjector; + XnFloat fDCmosEmitterDistance; + XnFloat fDCmosRCmosDistance; + XnFloat fReferenceDistance; + XnFloat fReferencePixelSize; + + // Clocks + XnInt32 nPllValue; + XnInt32 nSystemClockDivider; + XnInt32 nRCmosClockDivider; + XnInt32 nDCmosClockDivider; + XnInt32 nAdcClocDivider; + XnInt32 nI2CStandardSpeedHCount; + XnInt32 nI2CStandardSpeedLCount; + + XnInt32 nI2CHoldFixDelay; + + XnInt32 nSensorType; + XnInt32 nDebugMode; + XnInt32 nUseExtPhy; + XnInt32 bProjectorProtectionEnabled; + XnInt32 nProjectorDACOutputVoltage; + XnInt32 nProjectorDACOutputVoltage2; + XnInt32 nTecEmitterDelay; +} XnFixedParams; + +typedef struct XnFixedParamsV26 +{ + // Misc + XnInt32 nSerialNumber; + XnInt32 nWatchDogTimeout; + + // Flash + XnInt32 nFlashType; + XnInt32 nFlashSize; + XnInt32 nFlashBurstEnable; + XnInt32 nFmifReadBurstCycles; + XnInt32 nFmifReadAccessCycles; + XnInt32 nFmifReadRecoverCycles; + XnInt32 nFmifWriteAccessCycles; + XnInt32 nFmifWriteRecoverCycles; + XnInt32 nFmifWriteAssertionCycles; + + // Audio + XnInt32 nI2SLogicClockPolarity; + + // Depth + XnInt32 nDepthCiuHorizontalSyncPolarity; + XnInt32 nDepthCiuVerticalSyncPolarity; + XnInt32 nDepthCmosType; + XnInt32 nDepthCmosI2CAddress; + XnInt32 nDepthCmosI2CBus; + + // Image + XnInt32 nImageCiuHorizontalSyncPolarity; + XnInt32 nImageCiuVerticalSyncPolarity; + XnInt32 nImageCmosType; + XnInt32 nImageCmosI2CAddress; + XnInt32 nImageCmosI2CBus; + + // Geometry + XnInt32 nIrCmosCloseToProjector; + XnFloat fDCmosEmitterDistance; + XnFloat fDCmosRCmosDistance; + XnFloat fReferenceDistance; + XnFloat fReferencePixelSize; + + // Clocks + XnInt32 nPllValue; + XnInt32 nSystemClockDivider; + XnInt32 nRCmosClockDivider; + XnInt32 nDCmosClockDivider; + XnInt32 nAdcClocDivider; + XnInt32 nI2CStandardSpeedHCount; + XnInt32 nI2CStandardSpeedLCount; + + XnInt32 nI2CHoldFixDelay; + + XnInt32 nSensorType; + XnInt32 nDebugMode; + XnInt32 nTecEmitterDelay; + XnInt32 nUseExtPhy; +} XnFixedParamsV26; + +typedef struct XnFixedParamsV20 +{ + // Misc + XnInt32 nSerialNumber; + XnInt32 nWatchDogTimeout; + + // Flash + XnInt32 nFlashType; + XnInt32 nFlashSize; + XnInt32 nFlashBurstEnable; + XnInt32 nFmifReadBurstCycles; + XnInt32 nFmifReadAccessCycles; + XnInt32 nFmifReadRecoverCycles; + XnInt32 nFmifWriteAccessCycles; + XnInt32 nFmifWriteRecoverCycles; + XnInt32 nFmifWriteAssertionCycles; + + // Audio + XnInt32 nI2SLogicClockPolarity; + + // Depth + XnInt32 nDepthCiuHorizontalSyncPolarity; + XnInt32 nDepthCiuVerticalSyncPolarity; + XnInt32 nDepthCmosType; + XnInt32 nDepthCmosI2CAddress; + XnInt32 nDepthCmosI2CBus; + + // Image + XnInt32 nImageCiuHorizontalSyncPolarity; + XnInt32 nImageCiuVerticalSyncPolarity; + XnInt32 nImageCmosType; + XnInt32 nImageCmosI2CAddress; + XnInt32 nImageCmosI2CBus; + + // Geometry + XnInt32 nIrCmosCloseToProjector; + XnFloat fDCmosEmitterDistance; + XnFloat fDCmosRCmosDistance; + XnFloat fReferenceDistance; + XnFloat fReferencePixelSize; + + // Clocks + XnInt32 nPllValue; + XnInt32 nSystemClockDivider; + XnInt32 nRCmosClockDivider; + XnInt32 nDCmosClockDivider; + XnInt32 nAdcClocDivider; + XnInt32 nI2CStandardSpeedHCount; + XnInt32 nI2CStandardSpeedLCount; + + XnInt32 nI2CHoldFixDelay; + + XnInt32 nSensorType; + XnInt32 nDebugMode; + XnInt32 nTecEmitterDelay; +} XnFixedParamsV20; + +typedef struct XnRegistrationInformation1000 +{ + XnRegistrationFunctionCoefficients FuncX; + XnRegistrationFunctionCoefficients FuncY; + XnDouble dBeta; +} XnRegistrationInformation1000; + +typedef struct XnRegistrationInformation1080 +{ + XnInt32 nRGS_DX_CENTER; + XnInt32 nRGS_AX; + XnInt32 nRGS_BX; + XnInt32 nRGS_CX; + XnInt32 nRGS_DX; + XnInt32 nRGS_DX_START; + XnInt32 nRGS_AY; + XnInt32 nRGS_BY; + XnInt32 nRGS_CY; + XnInt32 nRGS_DY; + XnInt32 nRGS_DY_START; + XnInt32 nRGS_DX_BETA_START; + XnInt32 nRGS_DY_BETA_START; + XnInt32 nRGS_ROLLOUT_BLANK; + XnInt32 nRGS_ROLLOUT_SIZE; + XnInt32 nRGS_DX_BETA_INC; + XnInt32 nRGS_DY_BETA_INC; + XnInt32 nRGS_DXDX_START; + XnInt32 nRGS_DXDY_START; + XnInt32 nRGS_DYDX_START; + XnInt32 nRGS_DYDY_START; + XnInt32 nRGS_DXDXDX_START; + XnInt32 nRGS_DYDXDX_START; + XnInt32 nRGS_DXDXDY_START; + XnInt32 nRGS_DYDXDY_START; + XnInt32 nBACK_COMP1; + XnInt32 nRGS_DYDYDX_START; + XnInt32 nBACK_COMP2; + XnInt32 nRGS_DYDYDY_START; +} XnRegistrationInformation1080; + +typedef struct XnRegistrationPaddingInformation +{ + XnUInt16 nStartLines; + XnUInt16 nEndLines; + XnUInt16 nCroppingLines; +} XnRegistrationPaddingInformation; + +typedef struct XnDepthInformation +{ + XnUInt16 nConstShift; +} XnDepthInformation; + +typedef struct XnFrequencyInformation +{ + XnFloat fDeviceFrequency; +} XnFrequencyInformation; + +typedef struct XnAudioSharedBuffer +{ + XnUInt32 nPacketCount; + XnUInt32 nPacketSize; + XnUInt32 nTimestampsListOffset; + XnUInt32 nBufferOffset; + XnUInt32 nWritePacketIndex; +} XnAudioSharedBuffer; + +#pragma pack (pop) + +class XnDeviceSensor : public XnDeviceBaseProxy +{ +public: + XnDeviceSensor(); + ~XnDeviceSensor(); + + static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); + static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); + + virtual XnStatus Init(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus Destroy(); + + static XnStatus DestroyStreamData(XnStreamData** ppStreamData); +}; + +XnStatus XnDeviceSensorSetParam(XnDevicePrivateData* pDevicePrivateData, const XnChar* cpParamName, const XnInt32 nValue); + +#endif diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorIO.cpp b/Source/XnDeviceSensorV2/XnDeviceSensorIO.cpp index 7dc79a4..f7efb21 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorIO.cpp +++ b/Source/XnDeviceSensorV2/XnDeviceSensorIO.cpp @@ -1,436 +1,476 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorIO.h" -#include "XnDeviceSensor.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_SENSOR_VENDOR_ID 0x1D27 -#define XN_SENSOR_VENDOR_ID_KINECT 0x045E -#define XN_SENSOR_2_0_PRODUCT_ID 0x0200 -#define XN_SENSOR_5_0_PRODUCT_ID 0x0500 -#define XN_SENSOR_6_0_PRODUCT_ID 0x0600 -#define XN_SENSOR_KINECT_PRODUCT_ID 0x02AE - -#if XN_PLATFORM == XN_PLATFORM_WIN32 - #include - DEFINE_GUID(GUID_CLASS_PSDRV_USB, 0xc3b5f022, 0x5a42, 0x1980, 0x19, 0x09, 0xea, 0x72, 0x09, 0x56, 0x01, 0xb1); - #define USB_DEVICE_EXTRA_PARAM (void*)&GUID_CLASS_PSDRV_USB -#else - #define USB_DEVICE_EXTRA_PARAM NULL -#endif - -//--------------------------------------------------------------------------- -// Enums -//--------------------------------------------------------------------------- -typedef enum -{ - XN_FW_USB_INTERFACE_ISO = 0, - XN_FW_USB_INTERFACE_BULK = 1, -} XnFWUsbInterface; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnSensorIO::XnSensorIO(XN_SENSOR_HANDLE* pSensorHandle) : - m_pSensorHandle(pSensorHandle), - m_bMiscSupported(FALSE) -{ -} - -XnSensorIO::~XnSensorIO() -{ - -} - -XnStatus XnSensorIO::OpenDevice(const XnChar* strPath) -{ - XnStatus nRetVal; - XnUSBDeviceSpeed DevSpeed; - - nRetVal = xnUSBInit(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_USB_ALREADY_INIT) - return nRetVal; - - xnLogVerbose(XN_MASK_DEVICE_IO, "Connecting to USB device..."); - - if (strstr(strPath, "\\\\?\\usb") == NULL) - { - strPath = NULL; - } - - // try to open a 6.0 device - xnLogVerbose(XN_MASK_DEVICE_IO, "Trying to open a 6.0 sensor..."); - nRetVal = xnUSBOpenDevice(XN_SENSOR_VENDOR_ID, XN_SENSOR_6_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, (void*)strPath, &m_pSensorHandle->USBDevice); - if (nRetVal == XN_STATUS_USB_DEVICE_NOT_FOUND) - { - // if not found, see if we have a 5.0 device - xnLogVerbose(XN_MASK_DEVICE_IO, "Can't find 6.0. Trying to open a 5.0 sensor..."); - nRetVal = xnUSBOpenDevice(XN_SENSOR_VENDOR_ID, XN_SENSOR_5_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, (void*)strPath, &m_pSensorHandle->USBDevice); - } - if (nRetVal == XN_STATUS_USB_DEVICE_NOT_FOUND) - { - // if not found, see if we have a 2.0 - 4.0 devices - xnLogVerbose(XN_MASK_DEVICE_IO, "Can't find 5.0. Trying to open an older sensor..."); - nRetVal = xnUSBOpenDevice(XN_SENSOR_VENDOR_ID, XN_SENSOR_2_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, (void*)strPath, &m_pSensorHandle->USBDevice); - } - if (nRetVal == XN_STATUS_USB_DEVICE_NOT_FOUND) - { - // if not found, try the kinect - xnLogVerbose(XN_MASK_DEVICE_IO, "Can't find 2.0 - 4.0. Trying to open a kinect sensor..."); - nRetVal = xnUSBOpenDevice(XN_SENSOR_VENDOR_ID_KINECT, XN_SENSOR_KINECT_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, (void*)strPath, &m_pSensorHandle->USBDevice); - } - - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnUSBGetDeviceSpeed(m_pSensorHandle->USBDevice, &DevSpeed); - XN_IS_STATUS_OK(nRetVal); - - if (DevSpeed != XN_USB_DEVICE_HIGH_SPEED) - { - XN_LOG_WARNING_RETURN(XN_STATUS_USB_UNKNOWN_DEVICE_SPEED, XN_MASK_DEVICE_IO, "Device is not high speed!"); - } - - // on older firmwares, control was sent over BULK endpoints. Check if this is the case - xnLogVerbose(XN_MASK_DEVICE_IO, "Trying to open endpoint 0x4 for control out (for old firmwares)..."); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x4, XN_USB_EP_BULK, XN_USB_DIRECTION_OUT, &m_pSensorHandle->ControlConnection.ControlOutConnectionEp); - if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND || nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE || nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_DIRECTION) - { - // this is not the case. use regular control endpoint (0) - m_pSensorHandle->ControlConnection.bIsBulk = FALSE; - } - else - { - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x85 for control in..."); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x85, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->ControlConnection.ControlInConnectionEp); - XN_IS_STATUS_OK(nRetVal); - - m_pSensorHandle->ControlConnection.bIsBulk = TRUE; - } - - xnLogInfo(XN_MASK_DEVICE_IO, "Connected to USB device"); - - return XN_STATUS_OK; -} - -XnStatus XnSensorIO::OpenDataEndPoints(XnSensorUsbInterface nInterface) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // try to set requested interface - if (nInterface != XN_SENSOR_USB_INTERFACE_DEFAULT) - { - XnFWUsbInterface nFWInterface; - switch (nInterface) - { - case XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS: - nFWInterface = XN_FW_USB_INTERFACE_ISO; - break; - case XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS: - nFWInterface = XN_FW_USB_INTERFACE_BULK; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_USB_INTERFACE_NOT_SUPPORTED, XN_MASK_DEVICE_IO, "Unknown interface type: %d", nInterface); - } - - xnLogVerbose(XN_MASK_DEVICE_IO, "Setting USB interface to %d...", nFWInterface); - nRetVal = xnUSBSetInterface(m_pSensorHandle->USBDevice, 0, nFWInterface); - XN_IS_STATUS_OK(nRetVal); - } - - xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoints..."); - - // up until v3.0/4.0, Image went over 0x82, depth on 0x83, audio on 0x86, and control was using bulk EPs, at 0x4 and 0x85. - // starting v3.0/4.0, Image is at 0x81, depth at 0x82, audio/misc at 0x83, and control is using actual control EPs. - // This means we are using the new Jungo USB Code - XnBool bNewUSB = TRUE; - - // Depth - m_pSensorHandle->DepthConnection.bIsISO = FALSE; - - xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x81 for depth..."); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x81, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); - if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND) - { - bNewUSB = FALSE; - xnLogVerbose(XN_MASK_DEVICE_IO, "Endpoint 0x81 does not exist. Trying old USB: Opening 0x82 for depth..."); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x82, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); - XN_IS_STATUS_OK(nRetVal); - } - else - { - if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) - { - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x81, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); - - m_pSensorHandle->DepthConnection.bIsISO = TRUE; - } - - bNewUSB = TRUE; - - XN_IS_STATUS_OK(nRetVal); - - if (m_pSensorHandle->DepthConnection.bIsISO == TRUE) - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Depth endpoint is isochronous."); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Depth endpoint is bulk."); - } - } - m_pSensorHandle->DepthConnection.bIsOpen = TRUE; - - nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->DepthConnection.UsbEp, &m_pSensorHandle->DepthConnection.nMaxPacketSize); - XN_IS_STATUS_OK(nRetVal); - - // check this matches requested interface (unless DEFAULT was requested) - if (nInterface == XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS && m_pSensorHandle->DepthConnection.bIsISO || - nInterface == XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS && !m_pSensorHandle->DepthConnection.bIsISO) - { - return (XN_STATUS_USB_INTERFACE_NOT_SUPPORTED); - } - - m_interface = m_pSensorHandle->DepthConnection.bIsISO ? XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS : XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS; - - // Image - XnUInt16 nImageEP = bNewUSB ? 0x82 : 0x83; - - m_pSensorHandle->ImageConnection.bIsISO = FALSE; - - xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x%hx for image...", nImageEP); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nImageEP, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->ImageConnection.UsbEp); - if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) - { - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nImageEP, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->ImageConnection.UsbEp); - - m_pSensorHandle->ImageConnection.bIsISO = TRUE; - } - - XN_IS_STATUS_OK(nRetVal); - - if (m_pSensorHandle->ImageConnection.bIsISO == TRUE) - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Image endpoint is isochronous."); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Image endpoint is bulk."); - } - - m_pSensorHandle->ImageConnection.bIsOpen = TRUE; - - nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->ImageConnection.UsbEp, &m_pSensorHandle->ImageConnection.nMaxPacketSize); - XN_IS_STATUS_OK(nRetVal); - - // Misc - XnUInt16 nMiscEP = bNewUSB ? 0x83 : 0x86; - - m_pSensorHandle->MiscConnection.bIsISO = FALSE; - - xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x%hx for misc...", nMiscEP); - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nMiscEP, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->MiscConnection.UsbEp); - if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) - { - nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nMiscEP, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->MiscConnection.UsbEp); - - m_pSensorHandle->MiscConnection.bIsISO = TRUE; - } - if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND) - { - // Firmware does not support misc... - m_pSensorHandle->MiscConnection.bIsOpen = FALSE; - m_bMiscSupported = FALSE; - - xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is not supported..."); - } - else if (nRetVal == XN_STATUS_OK) - { - m_pSensorHandle->MiscConnection.bIsOpen = TRUE; - m_bMiscSupported = TRUE; - - if (m_pSensorHandle->MiscConnection.bIsISO == TRUE) - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is isochronous."); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is bulk."); - } - } - else - { - return nRetVal; - } - - if (m_pSensorHandle->MiscConnection.bIsOpen) - { - nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->MiscConnection.UsbEp, &m_pSensorHandle->MiscConnection.nMaxPacketSize); - XN_IS_STATUS_OK(nRetVal); - } - - xnLogInfo(XN_MASK_DEVICE_IO, "Endpoints open"); - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnSensorIO::CloseDevice() -{ - XnStatus nRetVal; - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB depth read thread..."); - xnUSBShutdownReadThread(m_pSensorHandle->DepthConnection.UsbEp); - - if (m_pSensorHandle->DepthConnection.UsbEp != NULL) - { - nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->DepthConnection.UsbEp); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->DepthConnection.UsbEp = NULL; - } - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB image read thread..."); - xnUSBShutdownReadThread(m_pSensorHandle->ImageConnection.UsbEp); - - if (m_pSensorHandle->ImageConnection.UsbEp != NULL) - { - nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ImageConnection.UsbEp); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->ImageConnection.UsbEp = NULL; - } - - if (m_pSensorHandle->MiscConnection.bIsOpen) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB misc read thread..."); - xnUSBShutdownReadThread(m_pSensorHandle->MiscConnection.UsbEp); - - if (m_pSensorHandle->MiscConnection.UsbEp != NULL) - { - nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->MiscConnection.UsbEp); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->MiscConnection.UsbEp = NULL; - } - } - - if (m_pSensorHandle->ControlConnection.bIsBulk) - { - if (m_pSensorHandle->ControlConnection.ControlInConnectionEp != NULL) - { - nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ControlConnection.ControlInConnectionEp); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->ControlConnection.ControlInConnectionEp = NULL; - } - - if (m_pSensorHandle->ControlConnection.ControlOutConnectionEp != NULL) - { - nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ControlConnection.ControlOutConnectionEp); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->ControlConnection.ControlOutConnectionEp = NULL; - } - } - - if (m_pSensorHandle->USBDevice != NULL) - { - nRetVal = xnUSBCloseDevice(m_pSensorHandle->USBDevice); - XN_IS_STATUS_OK(nRetVal); - m_pSensorHandle->USBDevice = NULL; - } - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Device closed successfully"); - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnSensorIO::GetNumOfSensors(XnUInt32* pnNumSensors) -{ - XnStatus nRetVal = XN_STATUS_OK; - XnBool bIsPresent = FALSE; - - *pnNumSensors = 0; - - nRetVal = xnUSBInit(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_USB_ALREADY_INIT) - return nRetVal; - - // search for a v6.0 device - nRetVal = xnUSBIsDevicePresent(XN_SENSOR_VENDOR_ID, XN_SENSOR_6_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, &bIsPresent); - XN_IS_STATUS_OK(nRetVal); - - if (!bIsPresent) - { - // search for a v5.0 device - nRetVal = xnUSBIsDevicePresent(XN_SENSOR_VENDOR_ID, XN_SENSOR_5_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, &bIsPresent); - XN_IS_STATUS_OK(nRetVal); - } - - if (!bIsPresent) - { - // try searching for an older device - nRetVal = xnUSBIsDevicePresent(XN_SENSOR_VENDOR_ID, XN_SENSOR_2_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, &bIsPresent); - XN_IS_STATUS_OK(nRetVal); - } - - if (!bIsPresent) - { - // try searching for a kinect - nRetVal = xnUSBIsDevicePresent(XN_SENSOR_VENDOR_ID_KINECT, XN_SENSOR_KINECT_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, &bIsPresent); - XN_IS_STATUS_OK(nRetVal); - } - - if (bIsPresent == TRUE) - { - *pnNumSensors = 1; - } - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnSensorIO::SetCallback(XnUSBEventCallbackFunctionPtr pCallbackPtr, void* pCallbackData) -{ - //TODO: Support multiple sensors - this won't work for more than one. - XnStatus nRetVal = XN_STATUS_OK; - - // try to register callback to a 5.0 device - nRetVal = xnUSBSetCallbackHandler(XN_SENSOR_VENDOR_ID, XN_SENSOR_5_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, pCallbackPtr, pCallbackData); - if (nRetVal == XN_STATUS_USB_DEVICE_NOT_FOUND) - { - // if not found, see if we have a 2.0 - 4.0 devices - nRetVal = xnUSBSetCallbackHandler(XN_SENSOR_VENDOR_ID, XN_SENSOR_2_0_PRODUCT_ID, USB_DEVICE_EXTRA_PARAM, pCallbackPtr, pCallbackData); - } - - return nRetVal; -} + /***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorIO.h" +#include "XnDeviceSensor.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_VENDOR_ID 0x1D27 +#define XN_SENSOR_VENDOR_ID_KINECT 0x045E +#define XN_SENSOR_2_0_PRODUCT_ID 0x0200 +#define XN_SENSOR_5_0_PRODUCT_ID 0x0500 +#define XN_SENSOR_6_0_PRODUCT_ID 0x0600 +#define XN_SENSOR_KINECT_PRODUCT_ID 0x02AE + +#if XN_PLATFORM == XN_PLATFORM_WIN32 + #include + DEFINE_GUID(GUID_CLASS_PSDRV_USB, 0xc3b5f022, 0x5a42, 0x1980, 0x19, 0x09, 0xea, 0x72, 0x09, 0x56, 0x01, 0xb1); + #define USB_DEVICE_EXTRA_PARAM (void*)&GUID_CLASS_PSDRV_USB +#else + #define USB_DEVICE_EXTRA_PARAM NULL +#endif + +//--------------------------------------------------------------------------- +// Enums +//--------------------------------------------------------------------------- +typedef enum +{ + XN_FW_USB_INTERFACE_ISO = 0, + XN_FW_USB_INTERFACE_BULK = 1, +} XnFWUsbInterface; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnSensorIO::XnSensorIO(XN_SENSOR_HANDLE* pSensorHandle) : + m_pSensorHandle(pSensorHandle), + m_bMiscSupported(FALSE) +{ +} + +XnSensorIO::~XnSensorIO() +{ + +} + +XnStatus XnSensorIO::OpenDevice(const XnChar* strPath) +{ + XnStatus nRetVal; + XnUSBDeviceSpeed DevSpeed; + + nRetVal = xnUSBInit(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_USB_ALREADY_INIT) + return nRetVal; + + xnLogVerbose(XN_MASK_DEVICE_IO, "Connecting to USB device..."); + + XnConnectionString aConnections[1]; + if (strPath == NULL || strcmp(strPath, "*:0") == 0) + { + // support old style API + XnConnectionString aConnections[1]; + XnUInt32 nCount = 1; + nRetVal = EnumerateSensors(aConnections, &nCount); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_OUTPUT_BUFFER_OVERFLOW) + { + return nRetVal; + } + + strPath = aConnections[0]; + } + + // try to open a 6.0 device + xnLogVerbose(XN_MASK_DEVICE_IO, "Trying to open sensor '%s'...", strPath); + nRetVal = xnUSBOpenDeviceByPath(strPath, &m_pSensorHandle->USBDevice); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnUSBGetDeviceSpeed(m_pSensorHandle->USBDevice, &DevSpeed); + XN_IS_STATUS_OK(nRetVal); + + if (DevSpeed != XN_USB_DEVICE_HIGH_SPEED) + { + XN_LOG_WARNING_RETURN(XN_STATUS_USB_UNKNOWN_DEVICE_SPEED, XN_MASK_DEVICE_IO, "Device is not high speed!"); + } + + // on older firmwares, control was sent over BULK endpoints. Check if this is the case + xnLogVerbose(XN_MASK_DEVICE_IO, "Trying to open endpoint 0x4 for control out (for old firmwares)..."); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x4, XN_USB_EP_BULK, XN_USB_DIRECTION_OUT, &m_pSensorHandle->ControlConnection.ControlOutConnectionEp); + if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND || nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE || nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_DIRECTION) + { + // this is not the case. use regular control endpoint (0) + m_pSensorHandle->ControlConnection.bIsBulk = FALSE; + } + else + { + XN_IS_STATUS_OK(nRetVal); + + xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x85 for control in..."); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x85, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->ControlConnection.ControlInConnectionEp); + XN_IS_STATUS_OK(nRetVal); + + m_pSensorHandle->ControlConnection.bIsBulk = TRUE; + } + + xnLogInfo(XN_MASK_DEVICE_IO, "Connected to USB device"); + + strcpy(m_strDeviceName, strPath); + + return XN_STATUS_OK; +} + +XnStatus XnSensorIO::OpenDataEndPoints(XnSensorUsbInterface nInterface) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // try to set requested interface + if (nInterface != XN_SENSOR_USB_INTERFACE_DEFAULT) + { + XnFWUsbInterface nFWInterface; + switch (nInterface) + { + case XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS: + nFWInterface = XN_FW_USB_INTERFACE_ISO; + break; + case XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS: + nFWInterface = XN_FW_USB_INTERFACE_BULK; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_USB_INTERFACE_NOT_SUPPORTED, XN_MASK_DEVICE_IO, "Unknown interface type: %d", nInterface); + } + + xnLogVerbose(XN_MASK_DEVICE_IO, "Setting USB interface to %d...", nFWInterface); + nRetVal = xnUSBSetInterface(m_pSensorHandle->USBDevice, 0, nFWInterface); + XN_IS_STATUS_OK(nRetVal); + } + + xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoints..."); + + // up until v3.0/4.0, Image went over 0x82, depth on 0x83, audio on 0x86, and control was using bulk EPs, at 0x4 and 0x85. + // starting v3.0/4.0, Image is at 0x81, depth at 0x82, audio/misc at 0x83, and control is using actual control EPs. + // This means we are using the new Jungo USB Code + XnBool bNewUSB = TRUE; + + // Depth + m_pSensorHandle->DepthConnection.bIsISO = FALSE; + + xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x81 for depth..."); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x81, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); + if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND) + { + bNewUSB = FALSE; + xnLogVerbose(XN_MASK_DEVICE_IO, "Endpoint 0x81 does not exist. Trying old USB: Opening 0x82 for depth..."); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x82, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); + XN_IS_STATUS_OK(nRetVal); + } + else + { + if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) + { + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, 0x81, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->DepthConnection.UsbEp); + + m_pSensorHandle->DepthConnection.bIsISO = TRUE; + } + + bNewUSB = TRUE; + + XN_IS_STATUS_OK(nRetVal); + + if (m_pSensorHandle->DepthConnection.bIsISO == TRUE) + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Depth endpoint is isochronous."); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Depth endpoint is bulk."); + } + } + m_pSensorHandle->DepthConnection.bIsOpen = TRUE; + + nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->DepthConnection.UsbEp, &m_pSensorHandle->DepthConnection.nMaxPacketSize); + XN_IS_STATUS_OK(nRetVal); + + // check this matches requested interface (unless DEFAULT was requested) + if (nInterface == XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS && m_pSensorHandle->DepthConnection.bIsISO || + nInterface == XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS && !m_pSensorHandle->DepthConnection.bIsISO) + { + return (XN_STATUS_USB_INTERFACE_NOT_SUPPORTED); + } + + m_interface = m_pSensorHandle->DepthConnection.bIsISO ? XN_SENSOR_USB_INTERFACE_ISO_ENDPOINTS : XN_SENSOR_USB_INTERFACE_BULK_ENDPOINTS; + + // Image + XnUInt16 nImageEP = bNewUSB ? 0x82 : 0x83; + + m_pSensorHandle->ImageConnection.bIsISO = FALSE; + + xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x%hx for image...", nImageEP); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nImageEP, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->ImageConnection.UsbEp); + if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) + { + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nImageEP, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->ImageConnection.UsbEp); + + m_pSensorHandle->ImageConnection.bIsISO = TRUE; + } + + XN_IS_STATUS_OK(nRetVal); + + if (m_pSensorHandle->ImageConnection.bIsISO == TRUE) + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Image endpoint is isochronous."); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Image endpoint is bulk."); + } + + m_pSensorHandle->ImageConnection.bIsOpen = TRUE; + + nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->ImageConnection.UsbEp, &m_pSensorHandle->ImageConnection.nMaxPacketSize); + XN_IS_STATUS_OK(nRetVal); + + // Misc + XnUInt16 nMiscEP = bNewUSB ? 0x83 : 0x86; + + m_pSensorHandle->MiscConnection.bIsISO = FALSE; + + xnLogVerbose(XN_MASK_DEVICE_IO, "Opening endpoint 0x%hx for misc...", nMiscEP); + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nMiscEP, XN_USB_EP_BULK, XN_USB_DIRECTION_IN, &m_pSensorHandle->MiscConnection.UsbEp); + if (nRetVal == XN_STATUS_USB_WRONG_ENDPOINT_TYPE) + { + nRetVal = xnUSBOpenEndPoint(m_pSensorHandle->USBDevice, nMiscEP, XN_USB_EP_ISOCHRONOUS, XN_USB_DIRECTION_IN, &m_pSensorHandle->MiscConnection.UsbEp); + + m_pSensorHandle->MiscConnection.bIsISO = TRUE; + } + if (nRetVal == XN_STATUS_USB_ENDPOINT_NOT_FOUND) + { + // Firmware does not support misc... + m_pSensorHandle->MiscConnection.bIsOpen = FALSE; + m_bMiscSupported = FALSE; + + xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is not supported..."); + } + else if (nRetVal == XN_STATUS_OK) + { + m_pSensorHandle->MiscConnection.bIsOpen = TRUE; + m_bMiscSupported = TRUE; + + if (m_pSensorHandle->MiscConnection.bIsISO == TRUE) + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is isochronous."); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_IO, "Misc endpoint is bulk."); + } + } + else + { + return nRetVal; + } + + if (m_pSensorHandle->MiscConnection.bIsOpen) + { + nRetVal = xnUSBGetEndPointMaxPacketSize(m_pSensorHandle->MiscConnection.UsbEp, &m_pSensorHandle->MiscConnection.nMaxPacketSize); + XN_IS_STATUS_OK(nRetVal); + } + + xnLogInfo(XN_MASK_DEVICE_IO, "Endpoints open"); + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnSensorIO::CloseDevice() +{ + XnStatus nRetVal; + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB depth read thread..."); + xnUSBShutdownReadThread(m_pSensorHandle->DepthConnection.UsbEp); + + if (m_pSensorHandle->DepthConnection.UsbEp != NULL) + { + nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->DepthConnection.UsbEp); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->DepthConnection.UsbEp = NULL; + } + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB image read thread..."); + xnUSBShutdownReadThread(m_pSensorHandle->ImageConnection.UsbEp); + + if (m_pSensorHandle->ImageConnection.UsbEp != NULL) + { + nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ImageConnection.UsbEp); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->ImageConnection.UsbEp = NULL; + } + + if (m_pSensorHandle->MiscConnection.bIsOpen) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB misc read thread..."); + xnUSBShutdownReadThread(m_pSensorHandle->MiscConnection.UsbEp); + + if (m_pSensorHandle->MiscConnection.UsbEp != NULL) + { + nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->MiscConnection.UsbEp); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->MiscConnection.UsbEp = NULL; + } + } + + if (m_pSensorHandle->ControlConnection.bIsBulk) + { + if (m_pSensorHandle->ControlConnection.ControlInConnectionEp != NULL) + { + nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ControlConnection.ControlInConnectionEp); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->ControlConnection.ControlInConnectionEp = NULL; + } + + if (m_pSensorHandle->ControlConnection.ControlOutConnectionEp != NULL) + { + nRetVal = xnUSBCloseEndPoint(m_pSensorHandle->ControlConnection.ControlOutConnectionEp); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->ControlConnection.ControlOutConnectionEp = NULL; + } + } + + if (m_pSensorHandle->USBDevice != NULL) + { + nRetVal = xnUSBCloseDevice(m_pSensorHandle->USBDevice); + XN_IS_STATUS_OK(nRetVal); + m_pSensorHandle->USBDevice = NULL; + } + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Device closed successfully"); + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus Enumerate(XnUInt16 nProduct, XnStringsHash& devicesSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + const XnUSBConnectionString* astrDevicePaths; + XnUInt32 nCount; + + if(nProduct == XN_SENSOR_KINECT_PRODUCT_ID){ + nRetVal = xnUSBEnumerateDevices(XN_SENSOR_VENDOR_ID_KINECT, nProduct, &astrDevicePaths, &nCount); + } else { + nRetVal = xnUSBEnumerateDevices(XN_SENSOR_VENDOR_ID, nProduct, &astrDevicePaths, &nCount); + } + XN_IS_STATUS_OK(nRetVal); + + for (XnUInt32 i = 0; i < nCount; ++i) + { + nRetVal = devicesSet.Set(astrDevicePaths[i], NULL); + XN_IS_STATUS_OK(nRetVal); + } + + xnUSBFreeDevicesList(astrDevicePaths); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIO::EnumerateSensors(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + XnBool bIsPresent = FALSE; + + nRetVal = xnUSBInit(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_USB_ALREADY_INIT) + return nRetVal; + + XnStringsHash devicesSet; + + // search for a v6.0 device + nRetVal = Enumerate(XN_SENSOR_6_0_PRODUCT_ID, devicesSet); + XN_IS_STATUS_OK(nRetVal); + + // search for a v5.0 device + nRetVal = Enumerate(XN_SENSOR_5_0_PRODUCT_ID, devicesSet); + XN_IS_STATUS_OK(nRetVal); + + // try searching for an older device + nRetVal = Enumerate(XN_SENSOR_2_0_PRODUCT_ID, devicesSet); + XN_IS_STATUS_OK(nRetVal); + + // try searching for an kinect device + nRetVal = Enumerate(XN_SENSOR_KINECT_PRODUCT_ID, devicesSet); + XN_IS_STATUS_OK(nRetVal); + + + // now copy back + XnUInt32 nCount = 0; + for (XnStringsHash::ConstIterator it = devicesSet.begin(); it != devicesSet.end(); ++it, ++nCount) + { + if (nCount < *pnCount) + { + strcpy(aConnectionStrings[nCount], it.Key()); + } + } + + if (!bIsPresent) + { + // Find the KINECT + nRetVal = xnUSBIsDevicePresent( + XN_SENSOR_VENDOR_ID_KINECT + ,XN_SENSOR_KINECT_PRODUCT_ID + ,USB_DEVICE_EXTRA_PARAM + ,&bIsPresent + ); + XN_IS_STATUS_OK(nRetVal); + } + + if (nCount > *pnCount) + { + *pnCount = nCount; + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + // All is good... + *pnCount = nCount; + return (XN_STATUS_OK); +} + +XnStatus XnSensorIO::SetCallback(XnUSBEventCallbackFunctionPtr pCallbackPtr, void* pCallbackData) +{ + //TODO: Support multiple sensors - this won't work for more than one. + XnStatus nRetVal = XN_STATUS_OK; + + // try to register callback to a 5.0 device + nRetVal = xnUSBSetCallbackHandler(XN_SENSOR_VENDOR_ID, XN_SENSOR_5_0_PRODUCT_ID, NULL, pCallbackPtr, pCallbackData); + if (nRetVal == XN_STATUS_USB_DEVICE_NOT_FOUND) + { + // if not found, see if we have a 2.0 - 4.0 devices + nRetVal = xnUSBSetCallbackHandler(XN_SENSOR_VENDOR_ID, XN_SENSOR_2_0_PRODUCT_ID, NULL, pCallbackPtr, pCallbackData); + } + + return nRetVal; +} + +const XnChar* XnSensorIO::GetDevicePath() +{ + return m_strDeviceName; +} diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorIO.h b/Source/XnDeviceSensorV2/XnDeviceSensorIO.h index 4b43c3e..f47c94b 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorIO.h +++ b/Source/XnDeviceSensorV2/XnDeviceSensorIO.h @@ -1,103 +1,107 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_DEVICE_SENSOR_I_O_H__ -#define __XN_DEVICE_SENSOR_I_O_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include - -//--------------------------------------------------------------------------- -// Structures & Enums -//--------------------------------------------------------------------------- -typedef struct XnUsbConnection -{ - XN_USB_EP_HANDLE UsbEp; - - XnBool bIsOpen; - XnUInt8* pUSBBuffer; - XnUInt32 nUSBBufferReadOffset; - XnUInt32 nUSBBufferWriteOffset; - - XnUInt32 bIsISO; - XnUInt32 nMaxPacketSize; -} XnUsbConnection; - -typedef struct XnUsbControlConnection -{ - /* When true, control connection is implemented using bulk end points. */ - XnBool bIsBulk; - XN_USB_EP_HANDLE ControlOutConnectionEp; - XN_USB_EP_HANDLE ControlInConnectionEp; -} XnUsbControlConnection; - -typedef struct XN_SENSOR_HANDLE -{ - XN_USB_DEV_HANDLE USBDevice; - - XnUsbControlConnection ControlConnection; - XnUsbConnection DepthConnection; - XnUsbConnection ImageConnection; - XnUsbConnection MiscConnection; -// XnSensorRes SensorRes; - XnUInt8 nBoardVer; -} XN_SENSOR_HANDLE; - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -class XnSensorIO -{ -public: - XnSensorIO(XN_SENSOR_HANDLE* pSensorHandle); - ~XnSensorIO(); - - XnStatus OpenDevice(const XnChar* strPath); - - XnStatus OpenDataEndPoints(XnSensorUsbInterface nInterface); - - XnSensorUsbInterface GetCurrentInterface() { return m_interface; } - - XnStatus CloseDevice(); - - static XnStatus GetNumOfSensors(XnUInt32* pnNumSensors); - - inline XnBool IsMiscEndpointSupported() const { return m_bMiscSupported; } - - XnStatus SetCallback(XnUSBEventCallbackFunctionPtr pCallbackPtr, void* pCallbackData); - -private: - XN_SENSOR_HANDLE* m_pSensorHandle; - XnBool m_bMiscSupported; - XnSensorUsbInterface m_interface; -}; - -#endif //__XN_DEVICE_SENSOR_I_O_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_DEVICE_SENSOR_I_O_H__ +#define __XN_DEVICE_SENSOR_I_O_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Structures & Enums +//--------------------------------------------------------------------------- +typedef struct XnUsbConnection +{ + XN_USB_EP_HANDLE UsbEp; + + XnBool bIsOpen; + XnUInt8* pUSBBuffer; + XnUInt32 nUSBBufferReadOffset; + XnUInt32 nUSBBufferWriteOffset; + + XnUInt32 bIsISO; + XnUInt32 nMaxPacketSize; +} XnUsbConnection; + +typedef struct XnUsbControlConnection +{ + /* When true, control connection is implemented using bulk end points. */ + XnBool bIsBulk; + XN_USB_EP_HANDLE ControlOutConnectionEp; + XN_USB_EP_HANDLE ControlInConnectionEp; +} XnUsbControlConnection; + +typedef struct XN_SENSOR_HANDLE +{ + XN_USB_DEV_HANDLE USBDevice; + + XnUsbControlConnection ControlConnection; + XnUsbConnection DepthConnection; + XnUsbConnection ImageConnection; + XnUsbConnection MiscConnection; +// XnSensorRes SensorRes; + XnUInt8 nBoardVer; +} XN_SENSOR_HANDLE; + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +class XnSensorIO +{ +public: + XnSensorIO(XN_SENSOR_HANDLE* pSensorHandle); + ~XnSensorIO(); + + XnStatus OpenDevice(const XnChar* strPath); + + XnStatus OpenDataEndPoints(XnSensorUsbInterface nInterface); + + XnSensorUsbInterface GetCurrentInterface() { return m_interface; } + + XnStatus CloseDevice(); + + static XnStatus EnumerateSensors(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); + + inline XnBool IsMiscEndpointSupported() const { return m_bMiscSupported; } + + XnStatus SetCallback(XnUSBEventCallbackFunctionPtr pCallbackPtr, void* pCallbackData); + + const XnChar* GetDevicePath(); + +private: + XN_SENSOR_HANDLE* m_pSensorHandle; + XnBool m_bMiscSupported; + XnSensorUsbInterface m_interface; + XnChar m_strDeviceName[XN_DEVICE_MAX_STRING_LENGTH]; +}; + +#endif //__XN_DEVICE_SENSOR_I_O_H__ diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorInit.cpp b/Source/XnDeviceSensorV2/XnDeviceSensorInit.cpp index b82f633..05103bb 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorInit.cpp +++ b/Source/XnDeviceSensorV2/XnDeviceSensorInit.cpp @@ -1,233 +1,233 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" -#include "XnDeviceSensorInit.h" -#include "XnDeviceSensorProtocol.h" -#include "Bayer.h" -#include "Registration.h" -#include "XnHostProtocol.h" -#include -#include "XnSensor.h" - -#define XN_HOST_PROTOCOL_MUTEX_NAME "HostProtocolMutex" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnDeviceSensorInit(XnDevicePrivateData* pDevicePrivateData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceSensorAllocateBuffers(pDevicePrivateData); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateNamedMutex(&pDevicePrivateData->hExecuteMutex, XN_HOST_PROTOCOL_MUTEX_NAME); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDeviceSensorConfigureVersion(pDevicePrivateData); - XN_IS_STATUS_OK(nRetVal); - - BayerUpdateGamma(1.0); - - nRetVal = xnOSCreateCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensorOpenInputThreads(XnDevicePrivateData* pDevicePrivateData, XnBool bOpen1, XnBool bOpen2, XnBool bOpen3) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (bOpen2) - { - // Depth - pDevicePrivateData->pSpecificDepthUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->pSpecificDepthUsb->pDevicePrivateData = pDevicePrivateData; - pDevicePrivateData->pSpecificDepthUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.DepthConnection; - pDevicePrivateData->pSpecificDepthUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; - - if (pDevicePrivateData->pSpecificDepthUsb->pUsbConnection->bIsISO == TRUE) - { - pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes = XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.DepthConnection.nMaxPacketSize; - } - else - { - pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes = XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.DepthConnection.nMaxPacketSize; - } - - pDevicePrivateData->pSpecificDepthUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes; - } - - if (bOpen1) - { - // Image - pDevicePrivateData->pSpecificImageUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->pSpecificImageUsb->pDevicePrivateData = pDevicePrivateData; - pDevicePrivateData->pSpecificImageUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.ImageConnection; - pDevicePrivateData->pSpecificImageUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; - - if (pDevicePrivateData->pSpecificImageUsb->pUsbConnection->bIsISO == TRUE) - { - pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes = XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.ImageConnection.nMaxPacketSize; - } - else - { - pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes = XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.ImageConnection.nMaxPacketSize; - } - - pDevicePrivateData->pSpecificImageUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes; - } - - // Misc - if (bOpen3 && pDevicePrivateData->pSensor->IsMiscSupported()) - { - pDevicePrivateData->pSpecificMiscUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->pSpecificMiscUsb->pDevicePrivateData = pDevicePrivateData; - pDevicePrivateData->pSpecificMiscUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.MiscConnection; - pDevicePrivateData->pSpecificMiscUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; - - if (pDevicePrivateData->pSpecificMiscUsb->pUsbConnection->bIsISO == TRUE) - { - pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes = XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.MiscConnection.nMaxPacketSize; - } - else - { - pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes = XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.MiscConnection.nMaxPacketSize; - } - - pDevicePrivateData->pSpecificMiscUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes; - } - - // Switch depth & image EPs for older FWs - if (pDevicePrivateData->FWInfo.nFWVer <= XN_SENSOR_FW_VER_5_1) - { - XnSpecificUsbDevice* pTempUsbDevice = pDevicePrivateData->pSpecificDepthUsb; - pDevicePrivateData->pSpecificDepthUsb = pDevicePrivateData->pSpecificImageUsb; - pDevicePrivateData->pSpecificImageUsb = pTempUsbDevice; - } - - return XN_STATUS_OK; -} - -XnStatus XnDeviceSensorAllocateBuffers(XnDevicePrivateData* pDevicePrivateData) -{ - pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->SensorHandle.DepthConnection.nUSBBufferReadOffset = 0; - pDevicePrivateData->SensorHandle.DepthConnection.nUSBBufferWriteOffset = 0; - - pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->SensorHandle.ImageConnection.nUSBBufferReadOffset = 0; - pDevicePrivateData->SensorHandle.ImageConnection.nUSBBufferWriteOffset = 0; - - if (pDevicePrivateData->pSensor->IsMiscSupported()) - { - pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); - pDevicePrivateData->SensorHandle.MiscConnection.nUSBBufferReadOffset = 0; - pDevicePrivateData->SensorHandle.MiscConnection.nUSBBufferWriteOffset = 0; - } - else - { - pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer = NULL; - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensorFreeBuffers(XnDevicePrivateData* pDevicePrivateData) -{ - if (pDevicePrivateData->pTempDepth1 != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pTempDepth1); - } - - if (pDevicePrivateData->pTempImage1 != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pTempImage1); - } - - if (pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer); - } - - if (pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer); - } - - if (pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer); - } - - if (pDevicePrivateData->pSpecificDepthUsb != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificDepthUsb); - } - - if (pDevicePrivateData->pSpecificImageUsb != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificImageUsb); - } - - if (pDevicePrivateData->pSpecificMiscUsb != NULL) - { - XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificMiscUsb); - } - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensorConfigureVersion(XnDevicePrivateData* pDevicePrivateData) -{ - XnVersions Versions; - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnHostProtocolGetVersion(pDevicePrivateData, pDevicePrivateData->Version); - - // Strange bug: sometimes, when sending first command to device, no reply is received, so try again - if (nRetVal == XN_STATUS_USB_TRANSFER_TIMEOUT) - { - xnOSSleep(2000); - nRetVal = XnHostProtocolGetVersion(pDevicePrivateData, pDevicePrivateData->Version); - } - - if (nRetVal != XN_STATUS_OK) - { - return nRetVal; - } - - // Sensor HW Version is always 1.0 now... - pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_2_0; - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" +#include "XnDeviceSensorInit.h" +#include "XnDeviceSensorProtocol.h" +#include "Bayer.h" +#include "Registration.h" +#include "XnHostProtocol.h" +#include +#include "XnSensor.h" + +#define XN_HOST_PROTOCOL_MUTEX_NAME "HostProtocolMutex" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnDeviceSensorInit(XnDevicePrivateData* pDevicePrivateData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceSensorAllocateBuffers(pDevicePrivateData); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateNamedMutex(&pDevicePrivateData->hExecuteMutex, XN_HOST_PROTOCOL_MUTEX_NAME); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDeviceSensorConfigureVersion(pDevicePrivateData); + XN_IS_STATUS_OK(nRetVal); + + BayerUpdateGamma(1.0); + + nRetVal = xnOSCreateCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensorOpenInputThreads(XnDevicePrivateData* pDevicePrivateData, XnBool bOpen1, XnBool bOpen2, XnBool bOpen3) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (bOpen2) + { + // Depth + pDevicePrivateData->pSpecificDepthUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->pSpecificDepthUsb->pDevicePrivateData = pDevicePrivateData; + pDevicePrivateData->pSpecificDepthUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.DepthConnection; + pDevicePrivateData->pSpecificDepthUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; + + if (pDevicePrivateData->pSpecificDepthUsb->pUsbConnection->bIsISO == TRUE) + { + pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes = XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.DepthConnection.nMaxPacketSize; + } + else + { + pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes = XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.DepthConnection.nMaxPacketSize; + } + + pDevicePrivateData->pSpecificDepthUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificDepthUsb->nChunkReadBytes; + } + + if (bOpen1) + { + // Image + pDevicePrivateData->pSpecificImageUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->pSpecificImageUsb->pDevicePrivateData = pDevicePrivateData; + pDevicePrivateData->pSpecificImageUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.ImageConnection; + pDevicePrivateData->pSpecificImageUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; + + if (pDevicePrivateData->pSpecificImageUsb->pUsbConnection->bIsISO == TRUE) + { + pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes = XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.ImageConnection.nMaxPacketSize; + } + else + { + pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes = XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.ImageConnection.nMaxPacketSize; + } + + pDevicePrivateData->pSpecificImageUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificImageUsb->nChunkReadBytes; + } + + // Misc + if (bOpen3 && pDevicePrivateData->pSensor->IsMiscSupported()) + { + pDevicePrivateData->pSpecificMiscUsb = (XnSpecificUsbDevice*)xnOSMallocAligned(sizeof(XnSpecificUsbDevice), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->pSpecificMiscUsb->pDevicePrivateData = pDevicePrivateData; + pDevicePrivateData->pSpecificMiscUsb->pUsbConnection = &pDevicePrivateData->SensorHandle.MiscConnection; + pDevicePrivateData->pSpecificMiscUsb->CurrState.State = XN_WAITING_FOR_CONFIGURATION; + + if (pDevicePrivateData->pSpecificMiscUsb->pUsbConnection->bIsISO == TRUE) + { + pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes = XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO * pDevicePrivateData->SensorHandle.MiscConnection.nMaxPacketSize; + } + else + { + pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes = XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK * pDevicePrivateData->SensorHandle.MiscConnection.nMaxPacketSize; + } + + pDevicePrivateData->pSpecificMiscUsb->nIgnoreBytes = (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_0) ? 0 : pDevicePrivateData->pSpecificMiscUsb->nChunkReadBytes; + } + + // Switch depth & image EPs for older FWs + if (pDevicePrivateData->FWInfo.nFWVer <= XN_SENSOR_FW_VER_5_1) + { + XnSpecificUsbDevice* pTempUsbDevice = pDevicePrivateData->pSpecificDepthUsb; + pDevicePrivateData->pSpecificDepthUsb = pDevicePrivateData->pSpecificImageUsb; + pDevicePrivateData->pSpecificImageUsb = pTempUsbDevice; + } + + return XN_STATUS_OK; +} + +XnStatus XnDeviceSensorAllocateBuffers(XnDevicePrivateData* pDevicePrivateData) +{ + pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->SensorHandle.DepthConnection.nUSBBufferReadOffset = 0; + pDevicePrivateData->SensorHandle.DepthConnection.nUSBBufferWriteOffset = 0; + + pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->SensorHandle.ImageConnection.nUSBBufferReadOffset = 0; + pDevicePrivateData->SensorHandle.ImageConnection.nUSBBufferWriteOffset = 0; + + if (pDevicePrivateData->pSensor->IsMiscSupported()) + { + pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer = (XnUInt8*)xnOSCallocAligned(XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE, sizeof(XnUInt8), XN_DEFAULT_MEM_ALIGN); + pDevicePrivateData->SensorHandle.MiscConnection.nUSBBufferReadOffset = 0; + pDevicePrivateData->SensorHandle.MiscConnection.nUSBBufferWriteOffset = 0; + } + else + { + pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer = NULL; + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensorFreeBuffers(XnDevicePrivateData* pDevicePrivateData) +{ + if (pDevicePrivateData->pTempDepth1 != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pTempDepth1); + } + + if (pDevicePrivateData->pTempImage1 != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pTempImage1); + } + + if (pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.DepthConnection.pUSBBuffer); + } + + if (pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.ImageConnection.pUSBBuffer); + } + + if (pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->SensorHandle.MiscConnection.pUSBBuffer); + } + + if (pDevicePrivateData->pSpecificDepthUsb != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificDepthUsb); + } + + if (pDevicePrivateData->pSpecificImageUsb != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificImageUsb); + } + + if (pDevicePrivateData->pSpecificMiscUsb != NULL) + { + XN_ALIGNED_FREE_AND_NULL(pDevicePrivateData->pSpecificMiscUsb); + } + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensorConfigureVersion(XnDevicePrivateData* pDevicePrivateData) +{ + XnVersions Versions; + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnHostProtocolGetVersion(pDevicePrivateData, pDevicePrivateData->Version); + + // Strange bug: sometimes, when sending first command to device, no reply is received, so try again + if (nRetVal == XN_STATUS_USB_TRANSFER_TIMEOUT) + { + xnOSSleep(2000); + nRetVal = XnHostProtocolGetVersion(pDevicePrivateData, pDevicePrivateData->Version); + } + + if (nRetVal != XN_STATUS_OK) + { + return nRetVal; + } + + // Sensor HW Version is always 1.0 now... + pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_2_0; + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorInit.h b/Source/XnDeviceSensorV2/XnDeviceSensorInit.h index 6894130..7fdcbe3 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorInit.h +++ b/Source/XnDeviceSensorV2/XnDeviceSensorInit.h @@ -1,95 +1,95 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_DEVICESENSORINIT_H_ -#define _XN_DEVICESENSORINIT_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" -#include "XnDeviceSensorProtocol.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- - -#if XN_PLATFORM == XN_PLATFORM_WIN32 - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO 8*10 - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK 120 - #define XN_SENSOR_USB_IMAGE_BUFFERS 8 - - #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO 8*10 - #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK 120 - #define XN_SENSOR_USB_DEPTH_BUFFERS 8 - - #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO 104 - #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK 20 - #define XN_SENSOR_USB_MISC_BUFFERS 8 -#elif XN_PLATFORM == XN_PLATFORM_PS3 - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_ISO 0x1E000 - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_BULK 0x4000 - #define XN_SENSOR_USB_IMAGE_BUFFERS 1 - - #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE 0x4000 - #define XN_SENSOR_USB_DEPTH_BUFFERS 2 - - #define XN_SENSOR_USB_MISC_BUFFER_SIZE 0x1000 - #define XN_SENSOR_USB_MISC_BUFFERS 1 -#elif (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM) - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO 32 - #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK 40 - #define XN_SENSOR_USB_IMAGE_BUFFERS 16 - - #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO 32 - #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK 40 - #define XN_SENSOR_USB_DEPTH_BUFFERS 16 - - #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO 104 - #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK 20 - #define XN_SENSOR_USB_MISC_BUFFERS 5 -#endif - -#define XN_SENSOR_READ_THREAD_TIMEOUT 100 - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -XnStatus XnDeviceSensorInit(XnDevicePrivateData* pDevicePrivateData); - -XnStatus XnDeviceSensorAllocateBuffers(XnDevicePrivateData* pDevicePrivateData); -XnStatus XnDeviceSensorFreeBuffers(XnDevicePrivateData* pDevicePrivateData); - -XnStatus XnDeviceSensorConfigureVersion(XnDevicePrivateData* pDevicePrivateData); - -XnStatus XnDeviceSensorOpenInputThreads(XnDevicePrivateData* pDevicePrivateData, XnBool bOpen1, XnBool bOpen2, XnBool bOpen3); - -XnStatus XnDeviceSensorConfigure(XnDevicePrivateData* pDevicePrivateData); - -XnStatus XnDeviceSensorInitCmosData(XnDevicePrivateData* pDevicePrivateData); - -#endif //_XN_DEVICESENSORINIT_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_DEVICESENSORINIT_H_ +#define _XN_DEVICESENSORINIT_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" +#include "XnDeviceSensorProtocol.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +#if XN_PLATFORM == XN_PLATFORM_WIN32 + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO 8*10 + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK 120 + #define XN_SENSOR_USB_IMAGE_BUFFERS 8 + + #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO 8*10 + #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK 120 + #define XN_SENSOR_USB_DEPTH_BUFFERS 8 + + #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO 104 + #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK 20 + #define XN_SENSOR_USB_MISC_BUFFERS 8 +#elif XN_PLATFORM == XN_PLATFORM_PS3 + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_ISO 0x1E000 + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_BULK 0x4000 + #define XN_SENSOR_USB_IMAGE_BUFFERS 1 + + #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE 0x4000 + #define XN_SENSOR_USB_DEPTH_BUFFERS 2 + + #define XN_SENSOR_USB_MISC_BUFFER_SIZE 0x1000 + #define XN_SENSOR_USB_MISC_BUFFERS 1 +#elif (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM || XN_PLATFORM == XN_PLATFORM_MACOSX) + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_ISO 32 + #define XN_SENSOR_USB_IMAGE_BUFFER_SIZE_MULTIPLIER_BULK 40 + #define XN_SENSOR_USB_IMAGE_BUFFERS 16 + + #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_ISO 32 + #define XN_SENSOR_USB_DEPTH_BUFFER_SIZE_MULTIPLIER_BULK 40 + #define XN_SENSOR_USB_DEPTH_BUFFERS 16 + + #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_ISO 104 + #define XN_SENSOR_USB_MISC_BUFFER_SIZE_MULTIPLIER_BULK 20 + #define XN_SENSOR_USB_MISC_BUFFERS 5 +#endif + +#define XN_SENSOR_READ_THREAD_TIMEOUT 100 + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +XnStatus XnDeviceSensorInit(XnDevicePrivateData* pDevicePrivateData); + +XnStatus XnDeviceSensorAllocateBuffers(XnDevicePrivateData* pDevicePrivateData); +XnStatus XnDeviceSensorFreeBuffers(XnDevicePrivateData* pDevicePrivateData); + +XnStatus XnDeviceSensorConfigureVersion(XnDevicePrivateData* pDevicePrivateData); + +XnStatus XnDeviceSensorOpenInputThreads(XnDevicePrivateData* pDevicePrivateData, XnBool bOpen1, XnBool bOpen2, XnBool bOpen3); + +XnStatus XnDeviceSensorConfigure(XnDevicePrivateData* pDevicePrivateData); + +XnStatus XnDeviceSensorInitCmosData(XnDevicePrivateData* pDevicePrivateData); + +#endif //_XN_DEVICESENSORINIT_H_ diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.cpp b/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.cpp index 1b45e62..45e7e2c 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.cpp +++ b/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.cpp @@ -1,270 +1,270 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorProtocol.h" -#include "XnDeviceSensorIO.h" -#include "Uncomp.h" -#include "XnHostProtocol.h" -#include -#include -#include "XnStreamProcessor.h" -#include "XnSensor.h" -#include - -FILE* g_fUSBDump; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnDeviceSensorProtocolGetSensorInfo(XnDevicePrivateData* pDevicePrivateData, XnChar* csSensorID) -{ - // Local function variables - XnStatus nRetVal = XN_STATUS_OK; - - XnFixedParams FixedParams; - nRetVal = XnHostProtocolGetFixedParams(pDevicePrivateData, FixedParams); - XN_IS_STATUS_OK(nRetVal); - - sprintf(csSensorID, "%x", FixedParams.nSerialNumber); - - // All is good... - return (XN_STATUS_OK); -} - -XnBool XN_CALLBACK_TYPE XnDeviceSensorProtocolUsbEpCb(XnUChar* pBuffer, XnUInt32 nBufferSize, void* pCallbackData) -{ - XN_PROFILING_START_MT_SECTION("XnDeviceSensorProtocolUsbEpCb"); - - XnUInt32 nReadBytes; - XnUInt16 nMagic; - - XnSpecificUsbDevice* pDevice = (XnSpecificUsbDevice*)pCallbackData; - XnDevicePrivateData* pDevicePrivateData = pDevice->pDevicePrivateData; - XnUChar* pBufEnd = pBuffer + nBufferSize; - - XnSpecificUsbDeviceState* pCurrState = &pDevice->CurrState; - - while (pBuffer < pBufEnd) - { - switch (pCurrState->State) - { - case XN_WAITING_FOR_CONFIGURATION: - if (pDevicePrivateData->bIgnoreDataPackets) - { - // ignore this packet - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "ignoring %d bytes - device requested to ignore!", nBufferSize); - pBuffer = pBufEnd; - } - else - { - pCurrState->State = XN_IGNORING_GARBAGE; - pCurrState->nMissingBytesInState = pDevice->nIgnoreBytes; - } - break; - - case XN_IGNORING_GARBAGE: - // ignore first bytes on this endpoint. NOTE: due to a bug in the firmware, the first data received - // on each endpoint is corrupt, causing wrong timestamp calculation, causing future (true) timestamps - // to be calculated wrongly. By ignoring the first data received on each endpoint we hope to get - // only valid data. - nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); - - if (nReadBytes > 0) - { - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "ignoring %d bytes - ignore garbage phase!", nReadBytes); - pCurrState->nMissingBytesInState -= nReadBytes; - pBuffer += nReadBytes; - } - - if (pCurrState->nMissingBytesInState == 0) - { - pCurrState->State = XN_LOOKING_FOR_MAGIC; - pCurrState->nMissingBytesInState = sizeof(XnUInt16); - } - break; - - case XN_LOOKING_FOR_MAGIC: - nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nFWMagic); - - if (pCurrState->nMissingBytesInState == sizeof(XnUInt8) && // first byte already found - pBuffer[0] == ((XnUInt8*)&nMagic)[1]) // we have here second byte - { - // move to next byte - pBuffer++; - - // move to next state - pCurrState->CurrHeader.nMagic = nMagic; - pCurrState->State = XN_PACKET_HEADER; - pCurrState->nMissingBytesInState = sizeof(XnSensorProtocolResponseHeader); - break; - } - - while (pBuffer < pBufEnd) - { - if (nMagic == *(XnUInt16*)(pBuffer)) - { - pCurrState->CurrHeader.nMagic = nMagic; - pCurrState->State = XN_PACKET_HEADER; - pCurrState->nMissingBytesInState = sizeof(XnSensorProtocolResponseHeader); - break; - } - else - pBuffer++; - } - - if (pBuffer == pBufEnd && // magic wasn't found - pBuffer[-1] == ((XnUInt8*)&nMagic)[0]) // last byte in buffer is first in magic - { - // mark that we found first one - pCurrState->nMissingBytesInState--; - } - - break; - - case XN_PACKET_HEADER: - nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); - xnOSMemCopy((XnUChar*)&pCurrState->CurrHeader + sizeof(XnSensorProtocolResponseHeader) - pCurrState->nMissingBytesInState, - pBuffer, nReadBytes); - pCurrState->nMissingBytesInState -= nReadBytes; - pBuffer += nReadBytes; - - if (pCurrState->nMissingBytesInState == 0) - { - // we have entire header. Fix it - pCurrState->CurrHeader.nBufSize = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nBufSize); - pCurrState->CurrHeader.nMagic = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nMagic); - pCurrState->CurrHeader.nReserve = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nReserve); - pCurrState->CurrHeader.nTimeStamp = XN_PREPARE_VAR32_IN_BUFFER(pCurrState->CurrHeader.nTimeStamp); - pCurrState->CurrHeader.nType = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nType); - pCurrState->CurrHeader.nBufSize = xnOSEndianSwapUINT16(pCurrState->CurrHeader.nBufSize); - pCurrState->CurrHeader.nBufSize -= sizeof(XnSensorProtocolResponseHeader); - - pCurrState->State = XN_PACKET_DATA; - pCurrState->nMissingBytesInState = pCurrState->CurrHeader.nBufSize; - } - break; - - case XN_PACKET_DATA: - nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); - pDevicePrivateData->pSensor->GetFirmware()->GetStreams()->ProcessPacketChunk(&pCurrState->CurrHeader, pBuffer, pCurrState->CurrHeader.nBufSize - pCurrState->nMissingBytesInState, nReadBytes); - pBuffer += nReadBytes; - pCurrState->nMissingBytesInState -= nReadBytes; - - if (pCurrState->nMissingBytesInState == 0) - { - pCurrState->State = XN_LOOKING_FOR_MAGIC; - pCurrState->nMissingBytesInState = sizeof(XnUInt16); - } - break; - } - } - - XN_PROFILING_END_SECTION; - - return TRUE; -} - -XnStatus XnDeviceSensorProtocolFindStreamOfType(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar** ppStreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - const XnChar* strNames[100]; - XnUInt32 nCount = 100; - - nRetVal = pDevicePrivateData->pSensor->GetStreamNames(strNames, &nCount); - XN_IS_STATUS_OK(nRetVal); - - for (XnUInt32 i = 0; i < nCount; ++i) - { - XnChar strCurType[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = pDevicePrivateData->pSensor->GetProperty(strNames[i], XN_STREAM_PROPERTY_TYPE, strCurType); - XN_IS_STATUS_OK(nRetVal); - - if (strcmp(strType, strCurType) == 0) - { - *ppStreamName = strNames[i]; - return (XN_STATUS_OK); - } - } - - *ppStreamName = NULL; - return (XN_STATUS_NO_MATCH); -} - -XnStatus XnDeviceSensorProtocolDumpLastRawFrameImpl(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - const XnChar* strName; - nRetVal = XnDeviceSensorProtocolFindStreamOfType(pDevicePrivateData, strType, &strName); - XN_IS_STATUS_OK(nRetVal); - - XnUInt64 nMaxDataSize; - nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, &nMaxDataSize); - XN_IS_STATUS_OK(nRetVal); - - XnDynamicSizeBuffer dsb; - dsb.nMaxSize = (XnUInt32)nMaxDataSize; - dsb.pData = xnOSMallocAligned((XnUInt32)nMaxDataSize, XN_DEFAULT_MEM_ALIGN); - XN_VALIDATE_ALLOC_PTR(dsb.pData); - - nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_LAST_RAW_FRAME, XN_PACK_GENERAL_BUFFER(dsb)); - if (nRetVal != XN_STATUS_OK) - { - xnOSFreeAligned(dsb.pData); - return (nRetVal); - } - - xnOSSaveFile(strFileName, dsb.pData, dsb.nDataSize); - - xnOSFreeAligned(dsb.pData); - - return (XN_STATUS_OK); -} - -XnStatus XnDeviceSensorProtocolDumpLastRawFrame(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - printf("* Dumping %s...\n", strType); - - nRetVal = XnDeviceSensorProtocolDumpLastRawFrameImpl(pDevicePrivateData, strType, strFileName); - if (nRetVal != XN_STATUS_OK) - { - printf("** Failed! %s\n", xnGetStatusString(nRetVal)); - } - else - { - printf ("** Saved %s to %s\n", strType, strFileName); - } - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorProtocol.h" +#include "XnDeviceSensorIO.h" +#include "Uncomp.h" +#include "XnHostProtocol.h" +#include +#include +#include "XnStreamProcessor.h" +#include "XnSensor.h" +#include + +FILE* g_fUSBDump; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnDeviceSensorProtocolGetSensorInfo(XnDevicePrivateData* pDevicePrivateData, XnChar* csSensorID) +{ + // Local function variables + XnStatus nRetVal = XN_STATUS_OK; + + XnFixedParams FixedParams; + nRetVal = XnHostProtocolGetFixedParams(pDevicePrivateData, FixedParams); + XN_IS_STATUS_OK(nRetVal); + + sprintf(csSensorID, "%x", FixedParams.nSerialNumber); + + // All is good... + return (XN_STATUS_OK); +} + +XnBool XN_CALLBACK_TYPE XnDeviceSensorProtocolUsbEpCb(XnUChar* pBuffer, XnUInt32 nBufferSize, void* pCallbackData) +{ + XN_PROFILING_START_MT_SECTION("XnDeviceSensorProtocolUsbEpCb"); + + XnUInt32 nReadBytes; + XnUInt16 nMagic; + + XnSpecificUsbDevice* pDevice = (XnSpecificUsbDevice*)pCallbackData; + XnDevicePrivateData* pDevicePrivateData = pDevice->pDevicePrivateData; + XnUChar* pBufEnd = pBuffer + nBufferSize; + + XnSpecificUsbDeviceState* pCurrState = &pDevice->CurrState; + + while (pBuffer < pBufEnd) + { + switch (pCurrState->State) + { + case XN_WAITING_FOR_CONFIGURATION: + if (pDevicePrivateData->bIgnoreDataPackets) + { + // ignore this packet + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "ignoring %d bytes - device requested to ignore!", nBufferSize); + pBuffer = pBufEnd; + } + else + { + pCurrState->State = XN_IGNORING_GARBAGE; + pCurrState->nMissingBytesInState = pDevice->nIgnoreBytes; + } + break; + + case XN_IGNORING_GARBAGE: + // ignore first bytes on this endpoint. NOTE: due to a bug in the firmware, the first data received + // on each endpoint is corrupt, causing wrong timestamp calculation, causing future (true) timestamps + // to be calculated wrongly. By ignoring the first data received on each endpoint we hope to get + // only valid data. + nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); + + if (nReadBytes > 0) + { + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "ignoring %d bytes - ignore garbage phase!", nReadBytes); + pCurrState->nMissingBytesInState -= nReadBytes; + pBuffer += nReadBytes; + } + + if (pCurrState->nMissingBytesInState == 0) + { + pCurrState->State = XN_LOOKING_FOR_MAGIC; + pCurrState->nMissingBytesInState = sizeof(XnUInt16); + } + break; + + case XN_LOOKING_FOR_MAGIC: + nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nFWMagic); + + if (pCurrState->nMissingBytesInState == sizeof(XnUInt8) && // first byte already found + pBuffer[0] == ((XnUInt8*)&nMagic)[1]) // we have here second byte + { + // move to next byte + pBuffer++; + + // move to next state + pCurrState->CurrHeader.nMagic = nMagic; + pCurrState->State = XN_PACKET_HEADER; + pCurrState->nMissingBytesInState = sizeof(XnSensorProtocolResponseHeader); + break; + } + + while (pBuffer < pBufEnd) + { + if (nMagic == *(XnUInt16*)(pBuffer)) + { + pCurrState->CurrHeader.nMagic = nMagic; + pCurrState->State = XN_PACKET_HEADER; + pCurrState->nMissingBytesInState = sizeof(XnSensorProtocolResponseHeader); + break; + } + else + pBuffer++; + } + + if (pBuffer == pBufEnd && // magic wasn't found + pBuffer[-1] == ((XnUInt8*)&nMagic)[0]) // last byte in buffer is first in magic + { + // mark that we found first one + pCurrState->nMissingBytesInState--; + } + + break; + + case XN_PACKET_HEADER: + nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); + xnOSMemCopy((XnUChar*)&pCurrState->CurrHeader + sizeof(XnSensorProtocolResponseHeader) - pCurrState->nMissingBytesInState, + pBuffer, nReadBytes); + pCurrState->nMissingBytesInState -= nReadBytes; + pBuffer += nReadBytes; + + if (pCurrState->nMissingBytesInState == 0) + { + // we have entire header. Fix it + pCurrState->CurrHeader.nBufSize = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nBufSize); + pCurrState->CurrHeader.nMagic = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nMagic); + pCurrState->CurrHeader.nReserve = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nReserve); + pCurrState->CurrHeader.nTimeStamp = XN_PREPARE_VAR32_IN_BUFFER(pCurrState->CurrHeader.nTimeStamp); + pCurrState->CurrHeader.nType = XN_PREPARE_VAR16_IN_BUFFER(pCurrState->CurrHeader.nType); + pCurrState->CurrHeader.nBufSize = xnOSEndianSwapUINT16(pCurrState->CurrHeader.nBufSize); + pCurrState->CurrHeader.nBufSize -= sizeof(XnSensorProtocolResponseHeader); + + pCurrState->State = XN_PACKET_DATA; + pCurrState->nMissingBytesInState = pCurrState->CurrHeader.nBufSize; + } + break; + + case XN_PACKET_DATA: + nReadBytes = XN_MIN((XnUInt32)(pBufEnd - pBuffer), pCurrState->nMissingBytesInState); + pDevicePrivateData->pSensor->GetFirmware()->GetStreams()->ProcessPacketChunk(&pCurrState->CurrHeader, pBuffer, pCurrState->CurrHeader.nBufSize - pCurrState->nMissingBytesInState, nReadBytes); + pBuffer += nReadBytes; + pCurrState->nMissingBytesInState -= nReadBytes; + + if (pCurrState->nMissingBytesInState == 0) + { + pCurrState->State = XN_LOOKING_FOR_MAGIC; + pCurrState->nMissingBytesInState = sizeof(XnUInt16); + } + break; + } + } + + XN_PROFILING_END_SECTION; + + return TRUE; +} + +XnStatus XnDeviceSensorProtocolFindStreamOfType(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar** ppStreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + const XnChar* strNames[100]; + XnUInt32 nCount = 100; + + nRetVal = pDevicePrivateData->pSensor->GetStreamNames(strNames, &nCount); + XN_IS_STATUS_OK(nRetVal); + + for (XnUInt32 i = 0; i < nCount; ++i) + { + XnChar strCurType[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = pDevicePrivateData->pSensor->GetProperty(strNames[i], XN_STREAM_PROPERTY_TYPE, strCurType); + XN_IS_STATUS_OK(nRetVal); + + if (strcmp(strType, strCurType) == 0) + { + *ppStreamName = strNames[i]; + return (XN_STATUS_OK); + } + } + + *ppStreamName = NULL; + return (XN_STATUS_NO_MATCH); +} + +XnStatus XnDeviceSensorProtocolDumpLastRawFrameImpl(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + const XnChar* strName; + nRetVal = XnDeviceSensorProtocolFindStreamOfType(pDevicePrivateData, strType, &strName); + XN_IS_STATUS_OK(nRetVal); + + XnUInt64 nMaxDataSize; + nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, &nMaxDataSize); + XN_IS_STATUS_OK(nRetVal); + + XnDynamicSizeBuffer dsb; + dsb.nMaxSize = (XnUInt32)nMaxDataSize; + dsb.pData = xnOSMallocAligned((XnUInt32)nMaxDataSize, XN_DEFAULT_MEM_ALIGN); + XN_VALIDATE_ALLOC_PTR(dsb.pData); + + nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_LAST_RAW_FRAME, XN_PACK_GENERAL_BUFFER(dsb)); + if (nRetVal != XN_STATUS_OK) + { + xnOSFreeAligned(dsb.pData); + return (nRetVal); + } + + xnOSSaveFile(strFileName, dsb.pData, dsb.nDataSize); + + xnOSFreeAligned(dsb.pData); + + return (XN_STATUS_OK); +} + +XnStatus XnDeviceSensorProtocolDumpLastRawFrame(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + printf("* Dumping %s...\n", strType); + + nRetVal = XnDeviceSensorProtocolDumpLastRawFrameImpl(pDevicePrivateData, strType, strFileName); + if (nRetVal != XN_STATUS_OK) + { + printf("** Failed! %s\n", xnGetStatusString(nRetVal)); + } + else + { + printf ("** Saved %s to %s\n", strType, strFileName); + } + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.h b/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.h index f35bf8c..f81a89f 100644 --- a/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.h +++ b/Source/XnDeviceSensorV2/XnDeviceSensorProtocol.h @@ -1,138 +1,138 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_DEVICESENSORPROTOCOL_H_ -#define _XN_DEVICESENSORPROTOCOL_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" -#include "XnHostProtocol.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_SENSOR_PROTOCOL_SENSOR_CLOCK_LENGTH 2 -#define XN_SENSOR_PROTOCOL_SENSOR_VER_LENGTH 1 - -#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START 0x7100 -#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_BUFFER 0x7200 -#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END 0x7500 - -#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START 0x8100 -#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_BUFFER 0x8200 -#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END 0x8500 - -#define XN_SENSOR_PROTOCOL_RESPONSE_AUDIO_BUFFER 0x9200 - -#define XN_SENSOR_PROTOCOL_RESPONSE_GMC 0xa200 - -#define XN_SENSOR_PROTOCOL_RESPONSE_GMC_DEBUG 0xb200 -#define XN_SENSOR_PROTOCOL_RESPONSE_GMC_DEBUG_END 0xb500 - -#define XN_SENSOR_PROTOCOL_RESPONSE_WAVELENGTH_CORRECTION_DEBUG 0xc200 - -#define XN_SENSOR_PROTOCOL_RESPONSE_TEC_DEBUG 0xd200 - -#define XN_SENSOR_PROTOCOL_RESPONSE_PROJECTOR_FAULT_EVENT 0xdead - -#define XN_SENSOR_PROTOCOL_RESPONSE_OVERHEAT 0xf31f - -#define XN_SENSOR_PROTOCOL_MAX_BUFFER_SIZE 1024*1024 -#define XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE 4*1024*1024 -#define XN_SENSOR_PROTOCOL_USB_MAX_ZERO_READ_COUNTER 5 -#define XN_SENSOR_PROTOCOL_READ_SLEEP 100 -#define XN_SENSOR_PROTOCOL_READ_MAX_TRIES 30 - -#define XN_SENSOR_PROTOCOL_MAX_RECONFIG_TRIES 10 - -#define XN_SENSOR_PROTOCOL_START_CAPTURE_TRIES 5 -#define XN_SENSOR_PROTOCOL_START_CAPTURE_SLEEP 1000 - -#define XN_SENSOR_PROTOCOL_GMC_MAX_POINTS_IN_PACKET 100 - -/** the number of points to accumulate before processing takes place. */ -#define XN_GMC_MIN_COUNT_FOR_RUNNING 1000 - -//--------------------------------------------------------------------------- -// Structures -//--------------------------------------------------------------------------- -#pragma pack (push, 1) - -typedef struct XnSensorProtocolResponseHeader -{ - XnUInt16 nMagic; - XnUInt16 nType; - XnUInt8 nReserve; - XnUInt8 nUnknown; - XnUInt16 nBufSize; - XnUInt32 nTimeStamp; -} XnSensorProtocolResponseHeader; -#pragma pack (pop) // Undo the pack change... - -typedef enum -{ - XN_WAITING_FOR_CONFIGURATION, - XN_IGNORING_GARBAGE, - XN_LOOKING_FOR_MAGIC, - XN_HALF_MAGIC, - XN_PACKET_HEADER, - XN_PACKET_DATA -} XnMiniPacketState; - -typedef struct XnSpecificUsbDeviceState -{ - XnMiniPacketState State; - XnSensorProtocolResponseHeader CurrHeader; - XnUInt32 nMissingBytesInState; -} XnSpecificUsbDeviceState; - -typedef struct XnSpecificUsbDevice -{ - XnDevicePrivateData* pDevicePrivateData; - XnUsbConnection* pUsbConnection; - XnUInt32 nIgnoreBytes; - XnUInt32 nChunkReadBytes; - XnSpecificUsbDeviceState CurrState; -} XnSpecificUsbDevice; - - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -XnStatus XnDeviceSensorProtocolGetSensorInfo(XnDevicePrivateData* pDevicePrivateData, XnChar* csSensorID); - -XnBool XN_CALLBACK_TYPE XnDeviceSensorProtocolUsbEpCb(XnUChar* pBuffer, XnUInt32 nBufferSize, void* pCallbackData); - -XnStatus XnCalculateExpectedImageSize(XnDevicePrivateData* pDevicePrivateData, XnUInt32* pnExpectedSize); -void XnProcessUncompressedDepthPacket(XnSensorProtocolResponseHeader* pCurrHeader, XnUChar* pData, XnUInt32 nDataSize, XnBool bEOP, XnSpecificUsbDevice* pSpecificDevice); -XnStatus XnDeviceSensorProtocolUpdateImageProcessor(XnDevicePrivateData* pDevicePrivateData); - - - -#endif //_XN_DEVICESENSORPROTOCOL_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_DEVICESENSORPROTOCOL_H_ +#define _XN_DEVICESENSORPROTOCOL_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" +#include "XnHostProtocol.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_PROTOCOL_SENSOR_CLOCK_LENGTH 2 +#define XN_SENSOR_PROTOCOL_SENSOR_VER_LENGTH 1 + +#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START 0x7100 +#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_BUFFER 0x7200 +#define XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END 0x7500 + +#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START 0x8100 +#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_BUFFER 0x8200 +#define XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END 0x8500 + +#define XN_SENSOR_PROTOCOL_RESPONSE_AUDIO_BUFFER 0x9200 + +#define XN_SENSOR_PROTOCOL_RESPONSE_GMC 0xa200 + +#define XN_SENSOR_PROTOCOL_RESPONSE_GMC_DEBUG 0xb200 +#define XN_SENSOR_PROTOCOL_RESPONSE_GMC_DEBUG_END 0xb500 + +#define XN_SENSOR_PROTOCOL_RESPONSE_WAVELENGTH_CORRECTION_DEBUG 0xc200 + +#define XN_SENSOR_PROTOCOL_RESPONSE_TEC_DEBUG 0xd200 + +#define XN_SENSOR_PROTOCOL_RESPONSE_PROJECTOR_FAULT_EVENT 0xdead + +#define XN_SENSOR_PROTOCOL_RESPONSE_OVERHEAT 0xf31f + +#define XN_SENSOR_PROTOCOL_MAX_BUFFER_SIZE 1024*1024 +#define XN_SENSOR_PROTOCOL_USB_BUFFER_SIZE 4*1024*1024 +#define XN_SENSOR_PROTOCOL_USB_MAX_ZERO_READ_COUNTER 5 +#define XN_SENSOR_PROTOCOL_READ_SLEEP 100 +#define XN_SENSOR_PROTOCOL_READ_MAX_TRIES 30 + +#define XN_SENSOR_PROTOCOL_MAX_RECONFIG_TRIES 10 + +#define XN_SENSOR_PROTOCOL_START_CAPTURE_TRIES 5 +#define XN_SENSOR_PROTOCOL_START_CAPTURE_SLEEP 1000 + +#define XN_SENSOR_PROTOCOL_GMC_MAX_POINTS_IN_PACKET 100 + +/** the number of points to accumulate before processing takes place. */ +#define XN_GMC_MIN_COUNT_FOR_RUNNING 1000 + +//--------------------------------------------------------------------------- +// Structures +//--------------------------------------------------------------------------- +#pragma pack (push, 1) + +typedef struct XnSensorProtocolResponseHeader +{ + XnUInt16 nMagic; + XnUInt16 nType; + XnUInt8 nReserve; + XnUInt8 nUnknown; + XnUInt16 nBufSize; + XnUInt32 nTimeStamp; +} XnSensorProtocolResponseHeader; +#pragma pack (pop) // Undo the pack change... + +typedef enum +{ + XN_WAITING_FOR_CONFIGURATION, + XN_IGNORING_GARBAGE, + XN_LOOKING_FOR_MAGIC, + XN_HALF_MAGIC, + XN_PACKET_HEADER, + XN_PACKET_DATA +} XnMiniPacketState; + +typedef struct XnSpecificUsbDeviceState +{ + XnMiniPacketState State; + XnSensorProtocolResponseHeader CurrHeader; + XnUInt32 nMissingBytesInState; +} XnSpecificUsbDeviceState; + +typedef struct XnSpecificUsbDevice +{ + XnDevicePrivateData* pDevicePrivateData; + XnUsbConnection* pUsbConnection; + XnUInt32 nIgnoreBytes; + XnUInt32 nChunkReadBytes; + XnSpecificUsbDeviceState CurrState; +} XnSpecificUsbDevice; + + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +XnStatus XnDeviceSensorProtocolGetSensorInfo(XnDevicePrivateData* pDevicePrivateData, XnChar* csSensorID); + +XnBool XN_CALLBACK_TYPE XnDeviceSensorProtocolUsbEpCb(XnUChar* pBuffer, XnUInt32 nBufferSize, void* pCallbackData); + +XnStatus XnCalculateExpectedImageSize(XnDevicePrivateData* pDevicePrivateData, XnUInt32* pnExpectedSize); +void XnProcessUncompressedDepthPacket(XnSensorProtocolResponseHeader* pCurrHeader, XnUChar* pData, XnUInt32 nDataSize, XnBool bEOP, XnSpecificUsbDevice* pSpecificDevice); +XnStatus XnDeviceSensorProtocolUpdateImageProcessor(XnDevicePrivateData* pDevicePrivateData); + + + +#endif //_XN_DEVICESENSORPROTOCOL_H_ diff --git a/Source/XnDeviceSensorV2/XnExportedSensorDevice.cpp b/Source/XnDeviceSensorV2/XnExportedSensorDevice.cpp index bc627b9..f642c61 100644 --- a/Source/XnDeviceSensorV2/XnExportedSensorDevice.cpp +++ b/Source/XnDeviceSensorV2/XnExportedSensorDevice.cpp @@ -1,185 +1,190 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnExportedSensorDevice.h" -#include -#include "XnSensorDevice.h" -#include -#include -#include "XnSensorServer.h" - -//--------------------------------------------------------------------------- -// XnExportedSensorDevice class -//--------------------------------------------------------------------------- -XnExportedSensorDevice::XnExportedSensorDevice() -{} - -void XnExportedSensorDevice::FillCommonDescriptionFields(XnProductionNodeDescription* pDescription) -{ - strcpy(pDescription->strName, XN_DEVICE_NAME); - strcpy(pDescription->strVendor, XN_VENDOR_PRIMESENSE); - - pDescription->Version.nMajor = XN_PS_MAJOR_VERSION; - pDescription->Version.nMinor = XN_PS_MINOR_VERSION; - pDescription->Version.nMaintenance = XN_PS_MAINTENANCE_VERSION; - pDescription->Version.nBuild = XN_PS_BUILD_VERSION; -} - -void XnExportedSensorDevice::GetDescription(XnProductionNodeDescription* pDescription) -{ - FillCommonDescriptionFields(pDescription); - pDescription->Type = XN_NODE_TYPE_DEVICE; -} - -XnStatus XnExportedSensorDevice::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // enumerate connected sensors - XnUInt32 nCount = 0; - - // check if sensor is connected - nRetVal = XnSensor::Enumerate(NULL, &nCount); - if (nRetVal != XN_STATUS_OUTPUT_BUFFER_OVERFLOW) - { - // no sensor connected - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_NOT_CONNECTED, XN_MASK_DEVICE_SENSOR, "No PS sensor is connected!"); - } - - // allocate according to count - XnConnectionString* pConnStrings; - XN_VALIDATE_CALLOC(pConnStrings, XnConnectionString, nCount); - - nRetVal = XnSensor::Enumerate(pConnStrings, &nCount); - if (nRetVal != XN_STATUS_OK) - { - xnOSFree(pConnStrings); - return (nRetVal); - } - - XnProductionNodeDescription Description; - GetDescription(&Description); - - // each connection string is a sensor. return it - for (XnUInt32 i = 0; i < nCount; ++i) - { - nRetVal = TreesList.Add(Description, pConnStrings[i], NULL); - if (nRetVal != XN_STATUS_OK) - { - xnOSFree(pConnStrings); - return (nRetVal); - } - } - - xnOSFree(pConnStrings); - - return (XN_STATUS_OK); -} - -XnStatus XnExportedSensorDevice::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnChar strGlobalConfigFile[XN_FILE_MAX_PATH]; - nRetVal = XnSensor::ResolveGlobalConfigFileName(strGlobalConfigFile, XN_FILE_MAX_PATH, strConfigurationDir); - XN_IS_STATUS_OK(nRetVal); - - XnBool bEnableMultiProcess = TRUE; - XnUInt32 nValue; - if (XN_STATUS_OK == xnOSReadIntFromINI(strGlobalConfigFile, XN_CONFIG_FILE_SERVER_SECTION, XN_MODULE_PROPERTY_ENABLE_MULTI_PROCESS, &nValue)) - { - bEnableMultiProcess = (nValue == TRUE); - } - - XnDeviceBase* pSensor = NULL; - - if (bEnableMultiProcess) - { - XN_VALIDATE_NEW(pSensor, XnSensorClient); - } - else - { - XN_VALIDATE_NEW(pSensor, XnSensor); - } - - XnDeviceConfig config; - config.DeviceMode = XN_DEVICE_MODE_READ; - config.cpConnectionString = strCreationInfo; - config.SharingMode = XN_DEVICE_EXCLUSIVE; - config.pInitialValues = NULL; - - if (strConfigurationDir != NULL) - { - if (bEnableMultiProcess) - { - XnSensorClient* pClient = (XnSensorClient*)pSensor; - pClient->SetConfigDir(strConfigurationDir); - } - else - { - XnSensor* pActualSensor = (XnSensor*)pSensor; - pActualSensor->SetGlobalConfigFile(strGlobalConfigFile); - } - } - - nRetVal = pSensor->Init(&config); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pSensor); - return (nRetVal); - } - - XnSensorDevice* pDevice = XN_NEW(XnSensorDevice, context, pSensor, strInstanceName); - if (pDevice == NULL) - { - XN_DELETE(pSensor); - return (XN_STATUS_ALLOC_FAILED); - } - - nRetVal = pDevice->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pSensor); - return (nRetVal); - } - - *ppInstance = pDevice; - - return (XN_STATUS_OK); -} - -void XnExportedSensorDevice::Destroy(xn::ModuleProductionNode* pInstance) -{ - XnSensorDevice* pDevice = dynamic_cast(pInstance); - XnDeviceBase* pSensor = pDevice->GetSensor(); - pSensor->Destroy(); - XN_DELETE(pSensor); - XN_DELETE(pDevice); -} +/***************************************************************************** + * * + * PrimeSense Sensor 5.0 Alpha * + * Copyright (C) 2010 PrimeSense Ltd. * + * * + * This file is part of PrimeSense Common. * + * * + * PrimeSense Sensor is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * PrimeSense Sensor is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with PrimeSense Sensor. If not, see . * + * * + *****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnExportedSensorDevice.h" +#include +#include "XnSensorDevice.h" +#include +#include +#include "XnSensorServer.h" + +//--------------------------------------------------------------------------- +// XnExportedSensorDevice class +//--------------------------------------------------------------------------- +XnExportedSensorDevice::XnExportedSensorDevice() +{} + +void XnExportedSensorDevice::FillCommonDescriptionFields(XnProductionNodeDescription* pDescription) +{ + strcpy(pDescription->strName, XN_DEVICE_NAME); + strcpy(pDescription->strVendor, XN_VENDOR_PRIMESENSE); + + pDescription->Version.nMajor = XN_PS_MAJOR_VERSION; + pDescription->Version.nMinor = XN_PS_MINOR_VERSION; + pDescription->Version.nMaintenance = XN_PS_MAINTENANCE_VERSION; + pDescription->Version.nBuild = XN_PS_BUILD_VERSION; +} + +void XnExportedSensorDevice::GetDescription(XnProductionNodeDescription* pDescription) +{ + FillCommonDescriptionFields(pDescription); + pDescription->Type = XN_NODE_TYPE_DEVICE; +} + +XnStatus XnExportedSensorDevice::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // enumerate connected sensors + XnUInt32 nCount = 0; + + // check if sensor is connected + nRetVal = XnSensor::Enumerate(NULL, &nCount); + if (nRetVal != XN_STATUS_OUTPUT_BUFFER_OVERFLOW) + { + // no sensor connected + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_NOT_CONNECTED, XN_MASK_DEVICE_SENSOR, "No PS sensor is connected!"); + } + + // allocate according to count + XnConnectionString* pConnStrings; + XN_VALIDATE_CALLOC(pConnStrings, XnConnectionString, nCount); + + nRetVal = XnSensor::Enumerate(pConnStrings, &nCount); + if (nRetVal != XN_STATUS_OK) + { + xnOSFree(pConnStrings); + return (nRetVal); + } + + XnProductionNodeDescription Description; + GetDescription(&Description); + + // each connection string is a sensor. return it + for (XnUInt32 i = 0; i < nCount; ++i) + { + nRetVal = TreesList.Add(Description, pConnStrings[i], NULL); + if (nRetVal != XN_STATUS_OK) + { + xnOSFree(pConnStrings); + return (nRetVal); + } + } + + xnOSFree(pConnStrings); + + return (XN_STATUS_OK); +} + +XnStatus XnExportedSensorDevice::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnChar strGlobalConfigFile[XN_FILE_MAX_PATH]; + nRetVal = XnSensor::ResolveGlobalConfigFileName(strGlobalConfigFile, XN_FILE_MAX_PATH, strConfigurationDir); + XN_IS_STATUS_OK(nRetVal); + +#if (XN_PLATFORM == XN_PLATFORM_MACOSX) + XnBool bEnableMultiProcess = FALSE; +#else + + XnBool bEnableMultiProcess = TRUE; + XnUInt32 nValue; + if (XN_STATUS_OK == xnOSReadIntFromINI(strGlobalConfigFile, XN_CONFIG_FILE_SERVER_SECTION, XN_MODULE_PROPERTY_ENABLE_MULTI_PROCESS, &nValue)) + { + bEnableMultiProcess = (nValue == TRUE); + } +#endif + + XnDeviceBase* pSensor = NULL; + + if (bEnableMultiProcess) + { + XN_VALIDATE_NEW(pSensor, XnSensorClient); + } + else + { + XN_VALIDATE_NEW(pSensor, XnSensor); + } + + XnDeviceConfig config; + config.DeviceMode = XN_DEVICE_MODE_READ; + config.cpConnectionString = strCreationInfo; + config.SharingMode = XN_DEVICE_EXCLUSIVE; + config.pInitialValues = NULL; + + if (strConfigurationDir != NULL) + { + if (bEnableMultiProcess) + { + XnSensorClient* pClient = (XnSensorClient*)pSensor; + pClient->SetConfigDir(strConfigurationDir); + } + else + { + XnSensor* pActualSensor = (XnSensor*)pSensor; + pActualSensor->SetGlobalConfigFile(strGlobalConfigFile); + } + } + + nRetVal = pSensor->Init(&config); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pSensor); + return (nRetVal); + } + + XnSensorDevice* pDevice = XN_NEW(XnSensorDevice, context, pSensor, strInstanceName); + if (pDevice == NULL) + { + XN_DELETE(pSensor); + return (XN_STATUS_ALLOC_FAILED); + } + + nRetVal = pDevice->Init(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pSensor); + return (nRetVal); + } + + *ppInstance = pDevice; + + return (XN_STATUS_OK); +} + +void XnExportedSensorDevice::Destroy(xn::ModuleProductionNode* pInstance) +{ + XnSensorDevice* pDevice = dynamic_cast(pInstance); + XnDeviceBase* pSensor = pDevice->GetSensor(); + pSensor->Destroy(); + XN_DELETE(pSensor); + XN_DELETE(pDevice); +} diff --git a/Source/XnDeviceSensorV2/XnExportedSensorDevice.h b/Source/XnDeviceSensorV2/XnExportedSensorDevice.h index 7bd9d81..2754876 100644 --- a/Source/XnDeviceSensorV2/XnExportedSensorDevice.h +++ b/Source/XnDeviceSensorV2/XnExportedSensorDevice.h @@ -1,51 +1,51 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_EXPORTED_SENSOR_DEVICE_H__ -#define __XN_EXPORTED_SENSOR_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensor.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnExportedSensorDevice : public xn::ModuleExportedProductionNode -{ -public: - XnExportedSensorDevice(); - static void FillCommonDescriptionFields(XnProductionNodeDescription* pDescription); - void GetDescription(XnProductionNodeDescription* pDescription); - XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); - XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); - void Destroy(xn::ModuleProductionNode* pInstance); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_EXPORTED_SENSOR_DEVICE_H__ +#define __XN_EXPORTED_SENSOR_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensor.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnExportedSensorDevice : public xn::ModuleExportedProductionNode +{ +public: + XnExportedSensorDevice(); + static void FillCommonDescriptionFields(XnProductionNodeDescription* pDescription); + void GetDescription(XnProductionNodeDescription* pDescription); + XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); + XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); + void Destroy(xn::ModuleProductionNode* pInstance); +}; + #endif // __XN_EXPORTED_SENSOR_DEVICE_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnExportedSensorGenerator.cpp b/Source/XnDeviceSensorV2/XnExportedSensorGenerator.cpp index 2f4f8e0..5c37593 100644 --- a/Source/XnDeviceSensorV2/XnExportedSensorGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnExportedSensorGenerator.cpp @@ -1,125 +1,125 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnExportedSensorGenerator.h" -#include "XnExportedSensorDevice.h" -#include -#include "XnSensorGenerator.h" -#include - -//--------------------------------------------------------------------------- -// XnExportedSensorGenerator class -//--------------------------------------------------------------------------- -XnExportedSensorGenerator::XnExportedSensorGenerator(XnProductionNodeType Type, const XnChar* strStreamType) : -m_Type(Type) -{ - strcpy(m_strStreamType, strStreamType); -} - -void XnExportedSensorGenerator::GetDescription(XnProductionNodeDescription* pDescription) -{ - XnExportedSensorDevice::FillCommonDescriptionFields(pDescription); - pDescription->Type = m_Type; -} - -XnStatus XnExportedSensorGenerator::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnProductionNodeDescription Description; - GetDescription(&Description); - - xn::Query query; - query.SetVendor(XN_VENDOR_PRIMESENSE); - - nRetVal = context.AutoEnumerateOverSingleInput(TreesList, Description, NULL, XN_NODE_TYPE_DEVICE, pErrors, &query); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnExportedSensorGenerator::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // needed trees should contain a device node - if (pNeededTrees == NULL || pNeededTrees->Begin() == pNeededTrees->End()) - { - return XN_STATUS_MISSING_NEEDED_TREE; - } - - xn::NodeInfo deviceInfo = *(pNeededTrees->Begin()); - if (deviceInfo.GetDescription().Type != XN_NODE_TYPE_DEVICE) - { - return XN_STATUS_MISSING_NEEDED_TREE; - } - - // Get the sensor instance - xn::Device device; - nRetVal = deviceInfo.GetInstance(device); - XN_IS_STATUS_OK(nRetVal); - - XnDeviceBase* pSensor = NULL; - nRetVal = device.GetGeneralProperty(XN_SENSOR_PROPERTY_INSTANCE_POINTER, sizeof(XnDeviceBase*), &pSensor); - XN_IS_STATUS_OK(nRetVal); - - // create stream - nRetVal = pSensor->CreateStream(m_strStreamType, strInstanceName); - XN_IS_STATUS_OK(nRetVal); - - // create generator - XnSensorGenerator* pGenerator = CreateGenerator(context, device, pSensor, strInstanceName); - if (pGenerator == NULL) - { - pSensor->DestroyStream(strInstanceName); - return (XN_STATUS_ALLOC_FAILED); - } - - // and initialize it - nRetVal = pGenerator->Init(); - if (nRetVal != XN_STATUS_OK) - { - pSensor->DestroyStream(strInstanceName); - XN_DELETE(pGenerator); - return (nRetVal); - } - - *ppInstance = pGenerator; - - return (XN_STATUS_OK); -} - -void XnExportedSensorGenerator::Destroy(xn::ModuleProductionNode* pInstance) -{ - XnSensorGenerator* pGenerator = dynamic_cast(pInstance); - pGenerator->GetSensor()->DestroyStream(pGenerator->GetModuleName()); - XN_DELETE(pGenerator); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnExportedSensorGenerator.h" +#include "XnExportedSensorDevice.h" +#include +#include "XnSensorGenerator.h" +#include + +//--------------------------------------------------------------------------- +// XnExportedSensorGenerator class +//--------------------------------------------------------------------------- +XnExportedSensorGenerator::XnExportedSensorGenerator(XnProductionNodeType Type, const XnChar* strStreamType) : +m_Type(Type) +{ + strcpy(m_strStreamType, strStreamType); +} + +void XnExportedSensorGenerator::GetDescription(XnProductionNodeDescription* pDescription) +{ + XnExportedSensorDevice::FillCommonDescriptionFields(pDescription); + pDescription->Type = m_Type; +} + +XnStatus XnExportedSensorGenerator::EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnProductionNodeDescription Description; + GetDescription(&Description); + + xn::Query query; + query.SetVendor(XN_VENDOR_PRIMESENSE); + + nRetVal = context.AutoEnumerateOverSingleInput(TreesList, Description, NULL, XN_NODE_TYPE_DEVICE, pErrors, &query); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnExportedSensorGenerator::Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // needed trees should contain a device node + if (pNeededTrees == NULL || pNeededTrees->Begin() == pNeededTrees->End()) + { + return XN_STATUS_MISSING_NEEDED_TREE; + } + + xn::NodeInfo deviceInfo = *(pNeededTrees->Begin()); + if (deviceInfo.GetDescription().Type != XN_NODE_TYPE_DEVICE) + { + return XN_STATUS_MISSING_NEEDED_TREE; + } + + // Get the sensor instance + xn::Device device; + nRetVal = deviceInfo.GetInstance(device); + XN_IS_STATUS_OK(nRetVal); + + XnDeviceBase* pSensor = NULL; + nRetVal = device.GetGeneralProperty(XN_SENSOR_PROPERTY_INSTANCE_POINTER, sizeof(XnDeviceBase*), &pSensor); + XN_IS_STATUS_OK(nRetVal); + + // create stream + nRetVal = pSensor->CreateStream(m_strStreamType, strInstanceName); + XN_IS_STATUS_OK(nRetVal); + + // create generator + XnSensorGenerator* pGenerator = CreateGenerator(context, device, pSensor, strInstanceName); + if (pGenerator == NULL) + { + pSensor->DestroyStream(strInstanceName); + return (XN_STATUS_ALLOC_FAILED); + } + + // and initialize it + nRetVal = pGenerator->Init(); + if (nRetVal != XN_STATUS_OK) + { + pSensor->DestroyStream(strInstanceName); + XN_DELETE(pGenerator); + return (nRetVal); + } + + *ppInstance = pGenerator; + + return (XN_STATUS_OK); +} + +void XnExportedSensorGenerator::Destroy(xn::ModuleProductionNode* pInstance) +{ + XnSensorGenerator* pGenerator = dynamic_cast(pInstance); + pGenerator->GetSensor()->DestroyStream(pGenerator->GetModuleName()); + XN_DELETE(pGenerator); +} + diff --git a/Source/XnDeviceSensorV2/XnExportedSensorGenerator.h b/Source/XnDeviceSensorV2/XnExportedSensorGenerator.h index db271c1..1798fbe 100644 --- a/Source/XnDeviceSensorV2/XnExportedSensorGenerator.h +++ b/Source/XnDeviceSensorV2/XnExportedSensorGenerator.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_EXPORTED_SENSOR_GENERATOR_H__ -#define __XN_EXPORTED_SENSOR_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensor.h" -#include "XnSensorGenerator.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnExportedSensorGenerator : public xn::ModuleExportedProductionNode -{ -public: - XnExportedSensorGenerator(XnProductionNodeType Type, const XnChar* strStreamType); - - void GetDescription(XnProductionNodeDescription* pDescription); - XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); - XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); - void Destroy(xn::ModuleProductionNode* pInstance); - -protected: - virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) = 0; - -private: - XnProductionNodeType m_Type; - XnChar m_strStreamType[XN_DEVICE_MAX_STRING_LENGTH]; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_EXPORTED_SENSOR_GENERATOR_H__ +#define __XN_EXPORTED_SENSOR_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensor.h" +#include "XnSensorGenerator.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnExportedSensorGenerator : public xn::ModuleExportedProductionNode +{ +public: + XnExportedSensorGenerator(XnProductionNodeType Type, const XnChar* strStreamType); + + void GetDescription(XnProductionNodeDescription* pDescription); + XnStatus EnumerateProductionTrees(xn::Context& context, xn::NodeInfoList& TreesList, xn::EnumerationErrors* pErrors); + XnStatus Create(xn::Context& context, const XnChar* strInstanceName, const XnChar* strCreationInfo, xn::NodeInfoList* pNeededTrees, const XnChar* strConfigurationDir, xn::ModuleProductionNode** ppInstance); + void Destroy(xn::ModuleProductionNode* pInstance); + +protected: + virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) = 0; + +private: + XnProductionNodeType m_Type; + XnChar m_strStreamType[XN_DEVICE_MAX_STRING_LENGTH]; +}; + #endif // __XN_EXPORTED_SENSOR_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnFirmwareCommands.cpp b/Source/XnDeviceSensorV2/XnFirmwareCommands.cpp index a46ac34..842d64b 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareCommands.cpp +++ b/Source/XnDeviceSensorV2/XnFirmwareCommands.cpp @@ -1,55 +1,55 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFirmwareCommands.h" -#include "XnHostProtocol.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFirmwareCommands::XnFirmwareCommands(XnDevicePrivateData* pDevicePrivateData) : - m_pDevicePrivateData(pDevicePrivateData) -{ -} - -XnStatus XnFirmwareCommands::GetFirmwareParam(XnUInt16 nParam, XnUInt16* pnValue) -{ - return XnHostProtocolGetParam(m_pDevicePrivateData, nParam, *pnValue); -} - -XnStatus XnFirmwareCommands::SetFirmwareParam(XnUInt16 nParam, XnUInt16 nValue) -{ - return XnHostProtocolSetParam(m_pDevicePrivateData, nParam, nValue); -} - -XnStatus XnFirmwareCommands::SetMultipleFirmwareParams(XnInnerParamData* aParams, XnUInt32 nCount) -{ - return XnHostProtocolSetMultipleParams(m_pDevicePrivateData, nCount, aParams); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFirmwareCommands.h" +#include "XnHostProtocol.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFirmwareCommands::XnFirmwareCommands(XnDevicePrivateData* pDevicePrivateData) : + m_pDevicePrivateData(pDevicePrivateData) +{ +} + +XnStatus XnFirmwareCommands::GetFirmwareParam(XnUInt16 nParam, XnUInt16* pnValue) +{ + return XnHostProtocolGetParam(m_pDevicePrivateData, nParam, *pnValue); +} + +XnStatus XnFirmwareCommands::SetFirmwareParam(XnUInt16 nParam, XnUInt16 nValue) +{ + return XnHostProtocolSetParam(m_pDevicePrivateData, nParam, nValue); +} + +XnStatus XnFirmwareCommands::SetMultipleFirmwareParams(XnInnerParamData* aParams, XnUInt32 nCount) +{ + return XnHostProtocolSetMultipleParams(m_pDevicePrivateData, nCount, aParams); +} diff --git a/Source/XnDeviceSensorV2/XnFirmwareCommands.h b/Source/XnDeviceSensorV2/XnFirmwareCommands.h index d85b5c0..a07bc67 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareCommands.h +++ b/Source/XnDeviceSensorV2/XnFirmwareCommands.h @@ -1,56 +1,56 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FIRMWARE_COMMANDS_H__ -#define __XN_FIRMWARE_COMMANDS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* Implements the various firmware opcodes. -* TODO: all opcodes should move here from XnHostProtocol.cpp. -*/ -class XnFirmwareCommands -{ -public: - XnFirmwareCommands(XnDevicePrivateData* pDevicePrivateData); - - XnStatus GetFirmwareParam(XnUInt16 nParam, XnUInt16* pnValue); - XnStatus SetFirmwareParam(XnUInt16 nParam, XnUInt16 nValue); - XnStatus SetMultipleFirmwareParams(XnInnerParamData* aParams, XnUInt32 nCount); - -private: - XnDevicePrivateData* m_pDevicePrivateData; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FIRMWARE_COMMANDS_H__ +#define __XN_FIRMWARE_COMMANDS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* Implements the various firmware opcodes. +* TODO: all opcodes should move here from XnHostProtocol.cpp. +*/ +class XnFirmwareCommands +{ +public: + XnFirmwareCommands(XnDevicePrivateData* pDevicePrivateData); + + XnStatus GetFirmwareParam(XnUInt16 nParam, XnUInt16* pnValue); + XnStatus SetFirmwareParam(XnUInt16 nParam, XnUInt16 nValue); + XnStatus SetMultipleFirmwareParams(XnInnerParamData* aParams, XnUInt32 nCount); + +private: + XnDevicePrivateData* m_pDevicePrivateData; +}; + #endif //__XN_FIRMWARE_COMMANDS_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnFirmwareInfo.cpp b/Source/XnDeviceSensorV2/XnFirmwareInfo.cpp index 3cb366e..9d31aad 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareInfo.cpp +++ b/Source/XnDeviceSensorV2/XnFirmwareInfo.cpp @@ -1,31 +1,31 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- #include "XnFirmwareInfo.h" \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnFirmwareInfo.h b/Source/XnDeviceSensorV2/XnFirmwareInfo.h index 9177cac..765206e 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareInfo.h +++ b/Source/XnDeviceSensorV2/XnFirmwareInfo.h @@ -1,76 +1,76 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FIRMWARE_INFO_H__ -#define __XN_FIRMWARE_INFO_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnFirmwareInfo -{ -public: - XnFWVer nFWVer; - XnUInt16 nHostMagic; - XnUInt16 nFWMagic; - XnUInt16 nProtocolHeaderSize; - XnUInt16 nProtocolMaxPacketSize; - - XnParamCurrentMode nCurrMode; - - XnBool bAudioSupported; - - XnUInt16 nOpcodeGetVersion; - XnUInt16 nOpcodeKeepAlive; - XnUInt16 nOpcodeGetParam; - XnUInt16 nOpcodeSetParam; - XnUInt16 nOpcodeGetFixedParams; - XnUInt16 nOpcodeGetMode; - XnUInt16 nOpcodeSetMode; - XnUInt16 nOpcodeAlgorithmParams; - XnUInt16 nOpcodeReset; - XnUInt16 nOpcodeSetCmosBlanking; - XnUInt16 nOpcodeGetCmosBlanking; - - - XnBool bMirrorSupported; - - XnUInt16 nUSBDelayReceive; - XnUInt16 nUSBDelayExecutePreSend; - XnUInt16 nUSBDelayExecutePostSend; - XnUInt16 nUSBDelaySoftReset; - XnUInt16 nUSBDelaySetParamFlicker; - XnUInt16 nUSBDelaySetParamStream0Mode; - XnUInt16 nUSBDelaySetParamStream1Mode; - XnUInt16 nUSBDelaySetParamStream2Mode; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FIRMWARE_INFO_H__ +#define __XN_FIRMWARE_INFO_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnFirmwareInfo +{ +public: + XnFWVer nFWVer; + XnUInt16 nHostMagic; + XnUInt16 nFWMagic; + XnUInt16 nProtocolHeaderSize; + XnUInt16 nProtocolMaxPacketSize; + + XnParamCurrentMode nCurrMode; + + XnBool bAudioSupported; + + XnUInt16 nOpcodeGetVersion; + XnUInt16 nOpcodeKeepAlive; + XnUInt16 nOpcodeGetParam; + XnUInt16 nOpcodeSetParam; + XnUInt16 nOpcodeGetFixedParams; + XnUInt16 nOpcodeGetMode; + XnUInt16 nOpcodeSetMode; + XnUInt16 nOpcodeAlgorithmParams; + XnUInt16 nOpcodeReset; + XnUInt16 nOpcodeSetCmosBlanking; + XnUInt16 nOpcodeGetCmosBlanking; + + + XnBool bMirrorSupported; + + XnUInt16 nUSBDelayReceive; + XnUInt16 nUSBDelayExecutePreSend; + XnUInt16 nUSBDelayExecutePostSend; + XnUInt16 nUSBDelaySoftReset; + XnUInt16 nUSBDelaySetParamFlicker; + XnUInt16 nUSBDelaySetParamStream0Mode; + XnUInt16 nUSBDelaySetParamStream1Mode; + XnUInt16 nUSBDelaySetParamStream2Mode; +}; + #endif //__XN_FIRMWARE_INFO_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnFirmwareStreams.cpp b/Source/XnDeviceSensorV2/XnFirmwareStreams.cpp index 7d8f2d0..179248a 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareStreams.cpp +++ b/Source/XnDeviceSensorV2/XnFirmwareStreams.cpp @@ -1,340 +1,340 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFirmwareStreams.h" -#include -#include "XnSensor.h" - - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFirmwareStreams::XnFirmwareStreams(XnDevicePrivateData* pDevicePrivateData) : - m_pDevicePrivateData(pDevicePrivateData) -{ -} - -XnFirmwareStreams::~XnFirmwareStreams() -{ -} - -XnStatus XnFirmwareStreams::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnFirmwareStreamData tempData; - xnOSMemSet(&tempData, 0, sizeof(XnFirmwareStreamData)); - - // Depth - nRetVal = m_DepthProcessor.Init(); - XN_IS_STATUS_OK(nRetVal); - - tempData.pProcessorHolder = &m_DepthProcessor; - tempData.strType = XN_STREAM_TYPE_DEPTH; - nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_DEPTH, tempData); - XN_IS_STATUS_OK(nRetVal); - - // Image - nRetVal = m_ImageProcessor.Init(); - XN_IS_STATUS_OK(nRetVal); - - tempData.pProcessorHolder = &m_ImageProcessor; - tempData.strType = XN_STREAM_TYPE_IMAGE; - nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_IMAGE, tempData); - XN_IS_STATUS_OK(nRetVal); - - // IR (currently uses the same processor - tempData.pProcessorHolder = &m_ImageProcessor; - tempData.strType = XN_STREAM_TYPE_IR; - nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_IR, tempData); - XN_IS_STATUS_OK(nRetVal); - - // Audio - nRetVal = m_AudioProcessor.Init(); - XN_IS_STATUS_OK(nRetVal); - - tempData.pProcessorHolder = &m_AudioProcessor; - tempData.strType = XN_STREAM_TYPE_AUDIO; - nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_AUDIO, tempData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnFirmwareStreams::CheckClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first of all, make sure this stream isn't claimed already - XnFirmwareStreamData* pStreamData; - nRetVal = m_FirmwareStreams.Get(strType, pStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pStreamData->pOwner != NULL && pStreamData->pOwner != pOwner) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open more than one %s stream at a time!", strType); - } - - if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) - { - // check if IR stream is configured - XnFirmwareStreamData* pIRStreamData; - nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IR, pIRStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pIRStreamData->pOwner != NULL) - { - // check res - if (pIRStreamData->nRes != nRes && (pIRStreamData->nRes != XN_RESOLUTION_SXGA || nRes != XN_RESOLUTION_VGA)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot set depth stream to resolution %d when IR is set to resolution %d!", nRes, pIRStreamData->nRes); - } - - // Avin: Removed to enable 1280x1024 IR - /* - // check FPS - if (pIRStreamData->nFPS != nFPS) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Depth and IR streams must have the same FPS!"); - } - */ - } - } - else if (strcmp(strType, XN_STREAM_TYPE_IR) == 0) - { - // check if image is configured - XnFirmwareStreamData* pImageStreamData; - nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IMAGE, pImageStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pImageStreamData->pOwner != NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open IR stream when image stream is on!"); - } - - // check if depth is configured - XnFirmwareStreamData* pDepthStreamData; - nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_DEPTH, pDepthStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pDepthStreamData->pOwner != NULL) - { - // check res - if (pDepthStreamData->nRes != nRes && (nRes != XN_RESOLUTION_SXGA || pDepthStreamData->nRes != XN_RESOLUTION_VGA)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot set IR stream to resolution %d when Depth is set to resolution %d!", nRes, pDepthStreamData->nRes); - } - - // check FPS - // Avin: Removed to enable 1280x1024 IR - /* - - if (pDepthStreamData->nFPS != nFPS) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Depth and IR streams must have the same FPS!"); - } - */ - } - } - else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) - { - // check if IR is configured - XnFirmwareStreamData* pIRStreamData; - nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IR, pIRStreamData); - XN_IS_STATUS_OK(nRetVal); - - if (pIRStreamData->pOwner != NULL) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open Image stream when IR stream is on!"); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnFirmwareStreams::ClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check constraints - nRetVal = CheckClaimStream(strType, nRes, nFPS, pOwner); - XN_IS_STATUS_OK(nRetVal); - - // get stream data - XnFirmwareStreamData* pData; - nRetVal = m_FirmwareStreams.Get(strType, pData); - XN_IS_STATUS_OK(nRetVal); - - // update stream - pData->nRes = nRes; - pData->nFPS = nFPS; - pData->pOwner = pOwner; - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "FW Stream %s was claimed by %s", strType, pOwner->GetName()); - - return (XN_STATUS_OK); -} - -XnStatus XnFirmwareStreams::ReleaseStream(const XnChar* strType, XnDeviceStream* pOwner) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get stream data - XnFirmwareStreamData* pData; - nRetVal = m_FirmwareStreams.Get(strType, pData); - XN_IS_STATUS_OK(nRetVal); - - if (pData->pOwner == NULL || pData->pOwner != pOwner) - { - return XN_STATUS_ERROR; - } - - // release it - pData->pOwner = NULL; - pData->pProcessorHolder->Replace(NULL); - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s released FW Stream %s", pOwner->GetName(), strType); - - return (XN_STATUS_OK); -} - -XnStatus XnFirmwareStreams::LockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get stream data - XnFirmwareStreamData* pData; - nRetVal = m_FirmwareStreams.Get(strType, pData); - XN_IS_STATUS_OK(nRetVal); - - if (pData->pOwner != pOwner) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to lock a processor for a non-owned stream!"); - } - - pData->pProcessorHolder->Lock(); - - return XN_STATUS_OK; -} - -XnStatus XnFirmwareStreams::UnlockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get stream data - XnFirmwareStreamData* pData; - nRetVal = m_FirmwareStreams.Get(strType, pData); - XN_IS_STATUS_OK(nRetVal); - - if (pData->pOwner != pOwner) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to unlock a processor for a non-owned stream!"); - } - - pData->pProcessorHolder->Unlock(); - - return XN_STATUS_OK; -} - -XnStatus XnFirmwareStreams::ReplaceStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner, XnDataProcessor* pProcessor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get stream data - XnFirmwareStreamData* pData; - nRetVal = m_FirmwareStreams.Get(strType, pData); - XN_IS_STATUS_OK(nRetVal); - - if (pData->pOwner != pOwner) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to replace a processor for a non-owned stream!"); - } - - pData->pProcessorHolder->Replace(pProcessor); - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Firmware stream '%s' processor was replaced.", strType); - - return (XN_STATUS_OK); -} - -XnBool XnFirmwareStreams::IsClaimed(const XnChar* strType, XnDeviceStream* pStream) -{ - XnFirmwareStreamData* pData = NULL; - if (XN_STATUS_OK == m_FirmwareStreams.Get(strType, pData) && pData->pOwner == pStream) - return TRUE; - else - return FALSE; -} - -void XnFirmwareStreams::ProcessPacketChunk(XnSensorProtocolResponseHeader* pHeader, XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_MT_SECTION("XnFirmwareStreams::ProcessPacketChunk") - - XnDataProcessorHolder* pStreamProcessor = NULL; - - switch (pHeader->nType) - { - case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START: - case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_BUFFER: - case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END: - pStreamProcessor = &m_DepthProcessor; - break; - case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START: - case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_BUFFER: - case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END: - pStreamProcessor = &m_ImageProcessor; - break; - case XN_SENSOR_PROTOCOL_RESPONSE_AUDIO_BUFFER: - pStreamProcessor = &m_AudioProcessor; - break; - case XN_SENSOR_PROTOCOL_RESPONSE_PROJECTOR_FAULT_EVENT: - m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_DEVICE_PROJECTOR_FAULT); - break; - case XN_SENSOR_PROTOCOL_RESPONSE_OVERHEAT: - m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_DEVICE_OVERHEAT); - break; - default: - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Unknown packet type (0x%x)!!!", pHeader->nType); - break; - } - - if (pStreamProcessor != NULL) - { - if (m_pDevicePrivateData->pSensor->GetErrorState() != XN_STATUS_OK) - { - // all OK now. - m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_OK); - } - - pStreamProcessor->ProcessData(pHeader, pData, nDataOffset, nDataSize); - } - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFirmwareStreams.h" +#include +#include "XnSensor.h" + + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFirmwareStreams::XnFirmwareStreams(XnDevicePrivateData* pDevicePrivateData) : + m_pDevicePrivateData(pDevicePrivateData) +{ +} + +XnFirmwareStreams::~XnFirmwareStreams() +{ +} + +XnStatus XnFirmwareStreams::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnFirmwareStreamData tempData; + xnOSMemSet(&tempData, 0, sizeof(XnFirmwareStreamData)); + + // Depth + nRetVal = m_DepthProcessor.Init(); + XN_IS_STATUS_OK(nRetVal); + + tempData.pProcessorHolder = &m_DepthProcessor; + tempData.strType = XN_STREAM_TYPE_DEPTH; + nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_DEPTH, tempData); + XN_IS_STATUS_OK(nRetVal); + + // Image + nRetVal = m_ImageProcessor.Init(); + XN_IS_STATUS_OK(nRetVal); + + tempData.pProcessorHolder = &m_ImageProcessor; + tempData.strType = XN_STREAM_TYPE_IMAGE; + nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_IMAGE, tempData); + XN_IS_STATUS_OK(nRetVal); + + // IR (currently uses the same processor + tempData.pProcessorHolder = &m_ImageProcessor; + tempData.strType = XN_STREAM_TYPE_IR; + nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_IR, tempData); + XN_IS_STATUS_OK(nRetVal); + + // Audio + nRetVal = m_AudioProcessor.Init(); + XN_IS_STATUS_OK(nRetVal); + + tempData.pProcessorHolder = &m_AudioProcessor; + tempData.strType = XN_STREAM_TYPE_AUDIO; + nRetVal = m_FirmwareStreams.Set(XN_STREAM_TYPE_AUDIO, tempData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnFirmwareStreams::CheckClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first of all, make sure this stream isn't claimed already + XnFirmwareStreamData* pStreamData; + nRetVal = m_FirmwareStreams.Get(strType, pStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pStreamData->pOwner != NULL && pStreamData->pOwner != pOwner) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open more than one %s stream at a time!", strType); + } + + if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) + { + // check if IR stream is configured + XnFirmwareStreamData* pIRStreamData; + nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IR, pIRStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pIRStreamData->pOwner != NULL) + { + // check res + if (pIRStreamData->nRes != nRes && (pIRStreamData->nRes != XN_RESOLUTION_SXGA || nRes != XN_RESOLUTION_VGA)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot set depth stream to resolution %d when IR is set to resolution %d!", nRes, pIRStreamData->nRes); + } + + // Avin: Removed to enable 1280x1024 IR + /* + // check FPS + if (pIRStreamData->nFPS != nFPS) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Depth and IR streams must have the same FPS!"); + } + */ + } + } + else if (strcmp(strType, XN_STREAM_TYPE_IR) == 0) + { + // check if image is configured + XnFirmwareStreamData* pImageStreamData; + nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IMAGE, pImageStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pImageStreamData->pOwner != NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open IR stream when image stream is on!"); + } + + // check if depth is configured + XnFirmwareStreamData* pDepthStreamData; + nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_DEPTH, pDepthStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pDepthStreamData->pOwner != NULL) + { + // check res + if (pDepthStreamData->nRes != nRes && (nRes != XN_RESOLUTION_SXGA || pDepthStreamData->nRes != XN_RESOLUTION_VGA)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot set IR stream to resolution %d when Depth is set to resolution %d!", nRes, pDepthStreamData->nRes); + } + + // check FPS + // Avin: Removed to enable 1280x1024 IR + /* + + if (pDepthStreamData->nFPS != nFPS) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Depth and IR streams must have the same FPS!"); + } + */ + } + } + else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) + { + // check if IR is configured + XnFirmwareStreamData* pIRStreamData; + nRetVal = m_FirmwareStreams.Get(XN_STREAM_TYPE_IR, pIRStreamData); + XN_IS_STATUS_OK(nRetVal); + + if (pIRStreamData->pOwner != NULL) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Cannot open Image stream when IR stream is on!"); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnFirmwareStreams::ClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check constraints + nRetVal = CheckClaimStream(strType, nRes, nFPS, pOwner); + XN_IS_STATUS_OK(nRetVal); + + // get stream data + XnFirmwareStreamData* pData; + nRetVal = m_FirmwareStreams.Get(strType, pData); + XN_IS_STATUS_OK(nRetVal); + + // update stream + pData->nRes = nRes; + pData->nFPS = nFPS; + pData->pOwner = pOwner; + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "FW Stream %s was claimed by %s", strType, pOwner->GetName()); + + return (XN_STATUS_OK); +} + +XnStatus XnFirmwareStreams::ReleaseStream(const XnChar* strType, XnDeviceStream* pOwner) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get stream data + XnFirmwareStreamData* pData; + nRetVal = m_FirmwareStreams.Get(strType, pData); + XN_IS_STATUS_OK(nRetVal); + + if (pData->pOwner == NULL || pData->pOwner != pOwner) + { + return XN_STATUS_ERROR; + } + + // release it + pData->pOwner = NULL; + pData->pProcessorHolder->Replace(NULL); + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s released FW Stream %s", pOwner->GetName(), strType); + + return (XN_STATUS_OK); +} + +XnStatus XnFirmwareStreams::LockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get stream data + XnFirmwareStreamData* pData; + nRetVal = m_FirmwareStreams.Get(strType, pData); + XN_IS_STATUS_OK(nRetVal); + + if (pData->pOwner != pOwner) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to lock a processor for a non-owned stream!"); + } + + pData->pProcessorHolder->Lock(); + + return XN_STATUS_OK; +} + +XnStatus XnFirmwareStreams::UnlockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get stream data + XnFirmwareStreamData* pData; + nRetVal = m_FirmwareStreams.Get(strType, pData); + XN_IS_STATUS_OK(nRetVal); + + if (pData->pOwner != pOwner) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to unlock a processor for a non-owned stream!"); + } + + pData->pProcessorHolder->Unlock(); + + return XN_STATUS_OK; +} + +XnStatus XnFirmwareStreams::ReplaceStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner, XnDataProcessor* pProcessor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get stream data + XnFirmwareStreamData* pData; + nRetVal = m_FirmwareStreams.Get(strType, pData); + XN_IS_STATUS_OK(nRetVal); + + if (pData->pOwner != pOwner) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Internal error: Trying to replace a processor for a non-owned stream!"); + } + + pData->pProcessorHolder->Replace(pProcessor); + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Firmware stream '%s' processor was replaced.", strType); + + return (XN_STATUS_OK); +} + +XnBool XnFirmwareStreams::IsClaimed(const XnChar* strType, XnDeviceStream* pStream) +{ + XnFirmwareStreamData* pData = NULL; + if (XN_STATUS_OK == m_FirmwareStreams.Get(strType, pData) && pData->pOwner == pStream) + return TRUE; + else + return FALSE; +} + +void XnFirmwareStreams::ProcessPacketChunk(XnSensorProtocolResponseHeader* pHeader, XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_MT_SECTION("XnFirmwareStreams::ProcessPacketChunk") + + XnDataProcessorHolder* pStreamProcessor = NULL; + + switch (pHeader->nType) + { + case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_START: + case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_BUFFER: + case XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END: + pStreamProcessor = &m_DepthProcessor; + break; + case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START: + case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_BUFFER: + case XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END: + pStreamProcessor = &m_ImageProcessor; + break; + case XN_SENSOR_PROTOCOL_RESPONSE_AUDIO_BUFFER: + pStreamProcessor = &m_AudioProcessor; + break; + case XN_SENSOR_PROTOCOL_RESPONSE_PROJECTOR_FAULT_EVENT: + m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_DEVICE_PROJECTOR_FAULT); + break; + case XN_SENSOR_PROTOCOL_RESPONSE_OVERHEAT: + m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_DEVICE_OVERHEAT); + break; + default: + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Unknown packet type (0x%x)!!!", pHeader->nType); + break; + } + + if (pStreamProcessor != NULL) + { + if (m_pDevicePrivateData->pSensor->GetErrorState() != XN_STATUS_OK) + { + // all OK now. + m_pDevicePrivateData->pSensor->SetErrorState(XN_STATUS_OK); + } + + pStreamProcessor->ProcessData(pHeader, pData, nDataOffset, nDataSize); + } + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnFirmwareStreams.h b/Source/XnDeviceSensorV2/XnFirmwareStreams.h index be747c8..bcf93d5 100644 --- a/Source/XnDeviceSensorV2/XnFirmwareStreams.h +++ b/Source/XnDeviceSensorV2/XnFirmwareStreams.h @@ -1,87 +1,87 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FIRMWARE_STREAMS_H__ -#define __XN_FIRMWARE_STREAMS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessorHolder.h" -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_STREAM_NAME_GMC "GMC" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnFirmwareStreams -{ -public: - XnFirmwareStreams(XnDevicePrivateData* pDevicePrivateData); - ~XnFirmwareStreams(); - - XnStatus Init(); - - XnStatus ClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner); - XnStatus ReleaseStream(const XnChar* strType, XnDeviceStream* pOwner); - XnStatus LockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner); - XnStatus UnlockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner); - XnStatus ReplaceStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner, XnDataProcessor* pProcessor); - XnBool IsClaimed(const XnChar* strType, XnDeviceStream* pStream); - - void ProcessPacketChunk(XnSensorProtocolResponseHeader* pHeader, XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - -private: - XnStatus CheckClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner); - - XnDevicePrivateData* m_pDevicePrivateData; - - class XnFirmwareStreamData - { - public: - XnDataProcessorHolder* pProcessorHolder; - const XnChar* strType; - XnResolutions nRes; - XnUInt32 nFPS; - XnDeviceStream* pOwner; - }; - - XN_DECLARE_STRINGS_HASH(XnFirmwareStreamData, XnFirmwareStreamsHash) - - XnFirmwareStreamsHash m_FirmwareStreams; - - XnDataProcessorHolder m_DepthProcessor; - XnDataProcessorHolder m_ImageProcessor; - XnDataProcessorHolder m_AudioProcessor; - -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FIRMWARE_STREAMS_H__ +#define __XN_FIRMWARE_STREAMS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessorHolder.h" +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_STREAM_NAME_GMC "GMC" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnFirmwareStreams +{ +public: + XnFirmwareStreams(XnDevicePrivateData* pDevicePrivateData); + ~XnFirmwareStreams(); + + XnStatus Init(); + + XnStatus ClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner); + XnStatus ReleaseStream(const XnChar* strType, XnDeviceStream* pOwner); + XnStatus LockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner); + XnStatus UnlockStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner); + XnStatus ReplaceStreamProcessor(const XnChar* strType, XnDeviceStream* pOwner, XnDataProcessor* pProcessor); + XnBool IsClaimed(const XnChar* strType, XnDeviceStream* pStream); + + void ProcessPacketChunk(XnSensorProtocolResponseHeader* pHeader, XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + +private: + XnStatus CheckClaimStream(const XnChar* strType, XnResolutions nRes, XnUInt32 nFPS, XnDeviceStream* pOwner); + + XnDevicePrivateData* m_pDevicePrivateData; + + class XnFirmwareStreamData + { + public: + XnDataProcessorHolder* pProcessorHolder; + const XnChar* strType; + XnResolutions nRes; + XnUInt32 nFPS; + XnDeviceStream* pOwner; + }; + + XN_DECLARE_STRINGS_HASH(XnFirmwareStreamData, XnFirmwareStreamsHash) + + XnFirmwareStreamsHash m_FirmwareStreams; + + XnDataProcessorHolder m_DepthProcessor; + XnDataProcessorHolder m_ImageProcessor; + XnDataProcessorHolder m_AudioProcessor; + +}; + #endif //__XN_FIRMWARE_STREAMS_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnFrameStreamProcessor.cpp b/Source/XnDeviceSensorV2/XnFrameStreamProcessor.cpp index cad4799..88902ad 100644 --- a/Source/XnDeviceSensorV2/XnFrameStreamProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnFrameStreamProcessor.cpp @@ -1,142 +1,142 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameStreamProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnFrameStreamProcessor::XnFrameStreamProcessor(XnFrameStream* pStream, XnSensorStreamHelper* pHelper, XnUInt16 nTypeSOF, XnUInt16 nTypeEOF) : - XnStreamProcessor(pStream, pHelper), - m_nTypeSOF(nTypeSOF), - m_nTypeEOF(nTypeEOF), - m_pTripleBuffer(pStream->GetTripleBuffer()), - m_InDump(XN_DUMP_CLOSED), - m_InternalDump(XN_DUMP_CLOSED), - m_bFrameCorrupted(FALSE) -{ - sprintf(m_csInDumpMask, "%sIn", pStream->GetType()); - sprintf(m_csInternalDumpMask, "Internal%s", pStream->GetType()); - xnDumpInit(&m_InDump, m_csInDumpMask, NULL, "%s_0.raw", m_csInDumpMask); - xnDumpInit(&m_InternalDump, m_csInternalDumpMask, NULL, "%s_0.raw", m_csInternalDumpMask); -} - -XnFrameStreamProcessor::~XnFrameStreamProcessor() -{ -} - -void XnFrameStreamProcessor::ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnFrameStreamProcessor::ProcessPacketChunk") - - // if first data from SOF packet - if (pHeader->nType == m_nTypeSOF && nDataOffset == 0) - { - OnStartOfFrame(pHeader); - } - - if (!m_bFrameCorrupted) - { - xnDumpWriteBuffer(m_InDump, pData, nDataSize); - ProcessFramePacketChunk(pHeader, pData, nDataOffset, nDataSize); - } - - // if last data from EOF packet - if (pHeader->nType == m_nTypeEOF && (nDataOffset + nDataSize) == pHeader->nBufSize) - { - OnEndOfFrame(pHeader); - } - - XN_PROFILING_END_SECTION -} - -void XnFrameStreamProcessor::OnPacketLost() -{ - FrameIsCorrupted(); -} - -void XnFrameStreamProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - m_bFrameCorrupted = FALSE; - m_pTripleBuffer->GetWriteBuffer()->Reset(); -} - -void XnFrameStreamProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - // write dump - XnBuffer* pCurWriteBuffer = m_pTripleBuffer->GetWriteBuffer(); - xnDumpWriteBuffer(m_InternalDump, pCurWriteBuffer->GetData(), pCurWriteBuffer->GetSize()); - xnDumpClose(&m_InternalDump); - xnDumpClose(&m_InDump); - - if (!m_bFrameCorrupted) - { - // mark the buffer as stable - XnUInt64 nTimestamp = GetTimeStamp(pHeader->nTimeStamp); - XnUInt32 nFrameID; - m_pTripleBuffer->MarkWriteBufferAsStable(nTimestamp, &nFrameID); - - // let inheriting classes do their stuff - OnFrameReady(nFrameID, nTimestamp); - } - else - { - // restart - m_pTripleBuffer->GetWriteBuffer()->Reset(); - } - - // log bandwidth - XnUInt64 nSysTime; - xnOSGetTimeStamp(&nSysTime); - xnDumpWriteString(m_pDevicePrivateData->BandwidthDump, "%llu,%s,%d,%d\n", - nSysTime, m_csName, GetCurrentFrameID(), m_nBytesReceived); - - // re-init dumps - xnDumpInit(&m_InDump, m_csInDumpMask, NULL, "%s_%d.raw", m_csInDumpMask, GetCurrentFrameID()); - xnDumpInit(&m_InternalDump, m_csInternalDumpMask, NULL, "%s_%d.raw", m_csInternalDumpMask, GetCurrentFrameID()); - m_nBytesReceived = 0; -} - -void XnFrameStreamProcessor::FrameIsCorrupted() -{ - if (!m_bFrameCorrupted) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s frame is corrupt!", m_csName); - m_bFrameCorrupted = TRUE; - } -} - -void XnFrameStreamProcessor::WriteBufferOverflowed() -{ - XnBuffer* pBuffer = GetWriteBuffer(); - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s Frame Buffer overflow! current size: %d", m_csName, pBuffer->GetSize()); - FrameIsCorrupted(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameStreamProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnFrameStreamProcessor::XnFrameStreamProcessor(XnFrameStream* pStream, XnSensorStreamHelper* pHelper, XnUInt16 nTypeSOF, XnUInt16 nTypeEOF) : + XnStreamProcessor(pStream, pHelper), + m_nTypeSOF(nTypeSOF), + m_nTypeEOF(nTypeEOF), + m_pTripleBuffer(pStream->GetTripleBuffer()), + m_InDump(XN_DUMP_CLOSED), + m_InternalDump(XN_DUMP_CLOSED), + m_bFrameCorrupted(FALSE) +{ + sprintf(m_csInDumpMask, "%sIn", pStream->GetType()); + sprintf(m_csInternalDumpMask, "Internal%s", pStream->GetType()); + xnDumpInit(&m_InDump, m_csInDumpMask, NULL, "%s_0.raw", m_csInDumpMask); + xnDumpInit(&m_InternalDump, m_csInternalDumpMask, NULL, "%s_0.raw", m_csInternalDumpMask); +} + +XnFrameStreamProcessor::~XnFrameStreamProcessor() +{ +} + +void XnFrameStreamProcessor::ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnFrameStreamProcessor::ProcessPacketChunk") + + // if first data from SOF packet + if (pHeader->nType == m_nTypeSOF && nDataOffset == 0) + { + OnStartOfFrame(pHeader); + } + + if (!m_bFrameCorrupted) + { + xnDumpWriteBuffer(m_InDump, pData, nDataSize); + ProcessFramePacketChunk(pHeader, pData, nDataOffset, nDataSize); + } + + // if last data from EOF packet + if (pHeader->nType == m_nTypeEOF && (nDataOffset + nDataSize) == pHeader->nBufSize) + { + OnEndOfFrame(pHeader); + } + + XN_PROFILING_END_SECTION +} + +void XnFrameStreamProcessor::OnPacketLost() +{ + FrameIsCorrupted(); +} + +void XnFrameStreamProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + m_bFrameCorrupted = FALSE; + m_pTripleBuffer->GetWriteBuffer()->Reset(); +} + +void XnFrameStreamProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + // write dump + XnBuffer* pCurWriteBuffer = m_pTripleBuffer->GetWriteBuffer(); + xnDumpWriteBuffer(m_InternalDump, pCurWriteBuffer->GetData(), pCurWriteBuffer->GetSize()); + xnDumpClose(&m_InternalDump); + xnDumpClose(&m_InDump); + + if (!m_bFrameCorrupted) + { + // mark the buffer as stable + XnUInt64 nTimestamp = GetTimeStamp(pHeader->nTimeStamp); + XnUInt32 nFrameID; + m_pTripleBuffer->MarkWriteBufferAsStable(nTimestamp, &nFrameID); + + // let inheriting classes do their stuff + OnFrameReady(nFrameID, nTimestamp); + } + else + { + // restart + m_pTripleBuffer->GetWriteBuffer()->Reset(); + } + + // log bandwidth + XnUInt64 nSysTime; + xnOSGetTimeStamp(&nSysTime); + xnDumpWriteString(m_pDevicePrivateData->BandwidthDump, "%llu,%s,%d,%d\n", + nSysTime, m_csName, GetCurrentFrameID(), m_nBytesReceived); + + // re-init dumps + xnDumpInit(&m_InDump, m_csInDumpMask, NULL, "%s_%d.raw", m_csInDumpMask, GetCurrentFrameID()); + xnDumpInit(&m_InternalDump, m_csInternalDumpMask, NULL, "%s_%d.raw", m_csInternalDumpMask, GetCurrentFrameID()); + m_nBytesReceived = 0; +} + +void XnFrameStreamProcessor::FrameIsCorrupted() +{ + if (!m_bFrameCorrupted) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s frame is corrupt!", m_csName); + m_bFrameCorrupted = TRUE; + } +} + +void XnFrameStreamProcessor::WriteBufferOverflowed() +{ + XnBuffer* pBuffer = GetWriteBuffer(); + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s Frame Buffer overflow! current size: %d", m_csName, pBuffer->GetSize()); + FrameIsCorrupted(); +} diff --git a/Source/XnDeviceSensorV2/XnFrameStreamProcessor.h b/Source/XnDeviceSensorV2/XnFrameStreamProcessor.h index 459ae88..0f43a02 100644 --- a/Source/XnDeviceSensorV2/XnFrameStreamProcessor.h +++ b/Source/XnDeviceSensorV2/XnFrameStreamProcessor.h @@ -1,179 +1,179 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_FRAME_STREAM_PROCESSOR_H__ -#define __XN_FRAME_STREAM_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -/* -* A processor for streams that are frame-based. -*/ -class XnFrameStreamProcessor : public XnStreamProcessor -{ -public: - /* - * Initializes a new frame-stream-processor. - * - * @param pDevicePrivateData [in] A pointer to the device. - * @param csName [in] Name of this stream. - * @param nTypeSOF [in] The packet type that signifies start-of-frame. - * @param nTypeEOF [in] The packet type that signifies end-of-frame. - */ - XnFrameStreamProcessor(XnFrameStream* pStream, XnSensorStreamHelper* pHelper, XnUInt16 nTypeSOF, XnUInt16 nTypeEOF); - - /** - * Destroys a frame-based stream processor - */ - virtual ~XnFrameStreamProcessor(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnPacketLost(); - - //--------------------------------------------------------------------------- - // New Virtual Functions - //--------------------------------------------------------------------------- - - /* - * Called when a frame starts. - * - * @param pHeader [in] Header for current packet. - */ - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - /* - * Called for every chunk received - * - * @param pHeader [in] A pointer to current packet header. - * @param pData [in] A pointer to the data. - * @param nDataOffset [in] The offset of this data chunk inside current packet. - * @param nDataSize [in] Size of the data in bytes. - */ - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) = 0; - - /* - * Called when a frame ends. - * - * @param pHeader [in] Header for current packet. - */ - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - /* - * Called when a frame is ready for reading. - * - * @param nFrameID [in] ID of this frame. - * @param nFrameTS [in] Timestamp of this frame. - */ - virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) {} - - //--------------------------------------------------------------------------- - // Utility Functions - //--------------------------------------------------------------------------- - - inline XnFrameStream* GetStream() - { - return (XnFrameStream*)XnStreamProcessor::GetStream(); - } - - /* - * Gets the expected output size. - */ - inline XnUInt32 GetExpectedOutputSize() - { - return GetStream()->GetRequiredDataSize(); - } - - /* - * Gets current write buffer. - */ - inline XnBuffer* GetWriteBuffer() - { - return m_pTripleBuffer->GetWriteBuffer(); - } - - /* - * Gets current frame ID (for logging purposes mainly). - */ - inline XnUInt32 GetCurrentFrameID() - { - return m_pTripleBuffer->GetLastFrameID(); - } - - /* - * Notifies that write buffer has overflowed, logging a warning and reseting it. - */ - void WriteBufferOverflowed(); - - /* - * Checks if write buffer has overflowed, if so, a log will be issued and buffer will reset. - */ - inline XnBool CheckWriteBufferForOverflow(XnUInt32 nWriteSize) - { - if (GetWriteBuffer()->GetFreeSpaceInBuffer() < nWriteSize) - { - WriteBufferOverflowed(); - return FALSE; - } - - return TRUE; - } - - /* - * Marks current frame as corrupted. - */ - void FrameIsCorrupted(); - -private: - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- - /* The type of start-of-frame packet. */ - XnUInt16 m_nTypeSOF; - /* The type of end-of-frame packet. */ - XnUInt16 m_nTypeEOF; - /* A pointer to the triple frame buffer of this stream. */ - XnFrameBufferManager* m_pTripleBuffer; - - XnChar m_csInDumpMask[100]; - XnChar m_csInternalDumpMask[100]; - XnDump m_InDump; - XnDump m_InternalDump; - XnBool m_bFrameCorrupted; -}; - -#endif //__XN_FRAME_STREAM_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_FRAME_STREAM_PROCESSOR_H__ +#define __XN_FRAME_STREAM_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +/* +* A processor for streams that are frame-based. +*/ +class XnFrameStreamProcessor : public XnStreamProcessor +{ +public: + /* + * Initializes a new frame-stream-processor. + * + * @param pDevicePrivateData [in] A pointer to the device. + * @param csName [in] Name of this stream. + * @param nTypeSOF [in] The packet type that signifies start-of-frame. + * @param nTypeEOF [in] The packet type that signifies end-of-frame. + */ + XnFrameStreamProcessor(XnFrameStream* pStream, XnSensorStreamHelper* pHelper, XnUInt16 nTypeSOF, XnUInt16 nTypeEOF); + + /** + * Destroys a frame-based stream processor + */ + virtual ~XnFrameStreamProcessor(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnPacketLost(); + + //--------------------------------------------------------------------------- + // New Virtual Functions + //--------------------------------------------------------------------------- + + /* + * Called when a frame starts. + * + * @param pHeader [in] Header for current packet. + */ + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + /* + * Called for every chunk received + * + * @param pHeader [in] A pointer to current packet header. + * @param pData [in] A pointer to the data. + * @param nDataOffset [in] The offset of this data chunk inside current packet. + * @param nDataSize [in] Size of the data in bytes. + */ + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) = 0; + + /* + * Called when a frame ends. + * + * @param pHeader [in] Header for current packet. + */ + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + /* + * Called when a frame is ready for reading. + * + * @param nFrameID [in] ID of this frame. + * @param nFrameTS [in] Timestamp of this frame. + */ + virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) {} + + //--------------------------------------------------------------------------- + // Utility Functions + //--------------------------------------------------------------------------- + + inline XnFrameStream* GetStream() + { + return (XnFrameStream*)XnStreamProcessor::GetStream(); + } + + /* + * Gets the expected output size. + */ + inline XnUInt32 GetExpectedOutputSize() + { + return GetStream()->GetRequiredDataSize(); + } + + /* + * Gets current write buffer. + */ + inline XnBuffer* GetWriteBuffer() + { + return m_pTripleBuffer->GetWriteBuffer(); + } + + /* + * Gets current frame ID (for logging purposes mainly). + */ + inline XnUInt32 GetCurrentFrameID() + { + return m_pTripleBuffer->GetLastFrameID(); + } + + /* + * Notifies that write buffer has overflowed, logging a warning and reseting it. + */ + void WriteBufferOverflowed(); + + /* + * Checks if write buffer has overflowed, if so, a log will be issued and buffer will reset. + */ + inline XnBool CheckWriteBufferForOverflow(XnUInt32 nWriteSize) + { + if (GetWriteBuffer()->GetFreeSpaceInBuffer() < nWriteSize) + { + WriteBufferOverflowed(); + return FALSE; + } + + return TRUE; + } + + /* + * Marks current frame as corrupted. + */ + void FrameIsCorrupted(); + +private: + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- + /* The type of start-of-frame packet. */ + XnUInt16 m_nTypeSOF; + /* The type of end-of-frame packet. */ + XnUInt16 m_nTypeEOF; + /* A pointer to the triple frame buffer of this stream. */ + XnFrameBufferManager* m_pTripleBuffer; + + XnChar m_csInDumpMask[100]; + XnChar m_csInternalDumpMask[100]; + XnDump m_InDump; + XnDump m_InternalDump; + XnBool m_bFrameCorrupted; +}; + +#endif //__XN_FRAME_STREAM_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnHostProtocol.cpp b/Source/XnDeviceSensorV2/XnHostProtocol.cpp index 6c4079b..24f4546 100644 --- a/Source/XnDeviceSensorV2/XnHostProtocol.cpp +++ b/Source/XnDeviceSensorV2/XnHostProtocol.cpp @@ -1,1532 +1,1532 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#include "XnDeviceSensorProtocol.h" -#include "XnHostProtocol.h" -#include -#include -#include "XnSensorDepthStream.h" -#include "XnSensor.h" -#include - -// Control Protocol -#include "XnParams.h" - -#define XN_RECEIVE_USB_DATA_TIMEOUT 20000 -#define XN_USB_HOST_PROTOCOL_TIMEOUT 5000 -#define XN_USB_HOST_PROTOCOL_TIMEOUT_KEEP_ALIVE 5000 -#define XN_USB_HOST_PROTOCOL_TIMEOUT_GETVERSION 5000 -#define XN_USB_HOST_PROTOCOL_TIMEOUT_SETPARAM 5000 - - -#define XN_USB_HOST_PROTOCOL_SEND_RETRIES 5 -#define XN_HOST_PROTOCOL_NOT_READY_RETRIES 3 - -#define XN_PROTOCOL_MAX_PACKET_SIZE_V5_0 512 -#define XN_PROTOCOL_MAX_PACKET_SIZE_V0_17 64 - -#define MAX_PACKET_SIZE 512 - -XnStatus XnHostProtocolInitFWParams(XnDevicePrivateData* pDevicePrivateData, XnFWVer nFWVer) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nFWVer) - { - case XN_SENSOR_FW_VER_5_3: - nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_2); - XN_IS_STATUS_OK(nRetVal); - - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - break; - - case XN_SENSOR_FW_VER_5_2: - nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); - XN_IS_STATUS_OK(nRetVal); - - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - break; - - case XN_SENSOR_FW_VER_5_1: - nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_0); - XN_IS_STATUS_OK(nRetVal); - - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_GET_CMOS_BLANKING; - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - break; - - case XN_SENSOR_FW_VER_5_0: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V5_0; - pDevicePrivateData->FWInfo.bAudioSupported = TRUE; - - pDevicePrivateData->FWInfo.bMirrorSupported = TRUE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_GET_MODE; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_SET_MODE; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_ALGORITM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_SET_CMOS_BLANKING; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - - break; - - case XN_SENSOR_FW_VER_4_0: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; - pDevicePrivateData->FWInfo.bAudioSupported = FALSE; - pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V400_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V400_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V400_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V400_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V400_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V400_GET_MODE; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V400_SET_MODE; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V400_ALGORITM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - break; - case XN_SENSOR_FW_VER_3_0: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; - pDevicePrivateData->FWInfo.bAudioSupported = TRUE; - pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V300_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V300_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V300_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V300_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V300_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V300_GET_MODE; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V300_SET_MODE; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V300_ALGORITM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - break; - case XN_SENSOR_FW_VER_1_2: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; - pDevicePrivateData->FWInfo.bAudioSupported = FALSE; - pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V110_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V110_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V110_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V110_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V110_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V110_GET_MODE; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V110_SET_MODE; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V110_ALGORITHM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - break; - case XN_SENSOR_FW_VER_1_1: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_25; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_25; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV25); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; - pDevicePrivateData->FWInfo.bAudioSupported = FALSE; - pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V110_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V110_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V110_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V110_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V110_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V110_GET_MODE; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V110_SET_MODE; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V110_ALGORITHM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - break; - case XN_SENSOR_FW_VER_0_17: - pDevicePrivateData->FWInfo.nFWVer = nFWVer; - pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_25; - pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_25; - pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV25); - pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; - pDevicePrivateData->FWInfo.bAudioSupported = FALSE; - pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; - - pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V017_GET_VERSION; - pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V017_KEEP_ALIVE; - pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V017_GET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V017_SET_PARAM; - pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V017_GET_FIXED_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V017_ALGORITM_PARAMS; - pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_V017_RESET; - pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; - pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; - - break; - default: - return (XN_STATUS_IO_DEVICE_WRONG_VERSION); - } - - pDevicePrivateData->FWInfo.nCurrMode = XN_MODE_PS; - - return (XN_STATUS_OK); -} - -XnStatus XnHostProtocolInitHeader(XnDevicePrivateData* pDevicePrivateData, void* pBuffer, void* pDataBuf, XnUInt32 nSize, XnUInt16 nOpcode) -{ - static XnUInt16 nId = 0; - - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) - { - XnHostProtocolHeaderV26* pHeader = (XnHostProtocolHeaderV26*)pBuffer; - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nHostMagic); - pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nSize/sizeof(XnUInt16))); - pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(nOpcode); - pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(nId++); - } - else - { - XnHostProtocolHeaderV25* pHeader = (XnHostProtocolHeaderV25*)pBuffer; - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nHostMagic); - pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nSize/sizeof(XnUInt16))); - pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(nOpcode); - pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(nId++); - pHeader->nCRC16 = XN_PREPARE_VAR16_IN_BUFFER(0); - } - - return (XN_STATUS_OK); -} - -XnStatus XnHostProtocolUSBSend(XnDevicePrivateData* pDevicePrivateData, - XnUChar* pBuffer, XnUInt16 nSize, XnUInt32& nRead, XnUInt32 nTimeOut, XnBool bForceBulk) -{ - XnStatus nRetVal; - - XnUsbControlConnection* pCtrlConnection = &pDevicePrivateData->SensorHandle.ControlConnection; - - XnUInt32 nCounter = XN_USB_HOST_PROTOCOL_SEND_RETRIES; - while (nCounter-- != 0) - { - if (pCtrlConnection->bIsBulk || bForceBulk) - nRetVal = xnUSBWriteEndPoint(pCtrlConnection->ControlOutConnectionEp, pBuffer, nSize, nTimeOut); - else - { - nRetVal = xnUSBSendControl(pDevicePrivateData->SensorHandle.USBDevice, XN_USB_CONTROL_TYPE_VENDOR, 0, 0, 0, pBuffer, nSize, nTimeOut); - } - - if (nRetVal != XN_STATUS_USB_TRANSFER_TIMEOUT && nRetVal != XN_STATUS_USB_TRANSFER_STALL) - break; - - xnOSSleep(100); - } - - return nRetVal; -} - -XnStatus XnHostProtocolUSBReceive(XnDevicePrivateData* pDevicePrivateData, - XnUChar* pBuffer, XnUInt nSize, XnUInt32& nRead, XnUInt32 nTimeOut, XnBool bForceBulk, XnUInt32 nFailTimeout) -{ - XnStatus nRetVal; - XnUInt64 nMaxTime; - XnUInt64 nCurrTime; - - XnUsbControlConnection* pCtrlConnection = &pDevicePrivateData->SensorHandle.ControlConnection; - - xnOSGetHighResTimeStamp(&nMaxTime); - nMaxTime += (nTimeOut * 1000); - - while (TRUE) - { - xnOSGetHighResTimeStamp(&nCurrTime); - if (nCurrTime > nMaxTime) - { - return (XN_STATUS_USB_TRANSFER_TIMEOUT); - } - - if (pCtrlConnection->bIsBulk || bForceBulk) - nRetVal = xnUSBReadEndPoint(pCtrlConnection->ControlInConnectionEp, pBuffer, nSize, &nRead, nTimeOut); - else - nRetVal = xnUSBReceiveControl(pDevicePrivateData->SensorHandle.USBDevice, XN_USB_CONTROL_TYPE_VENDOR, 0, 0, 0, pBuffer, nSize, &nRead, nTimeOut); - - if (nRetVal != XN_STATUS_USB_TRANSFER_TIMEOUT && nRetVal != XN_STATUS_USB_TRANSFER_STALL && nRetVal != XN_STATUS_USB_NOT_ENOUGH_DATA) - { - break; - } - - if (nFailTimeout != 0) - { - XnUInt64 nNow; - XnUInt64 nNow2; - xnOSGetHighResTimeStamp(&nNow); - xnOSGetHighResTimeStamp(&nNow2); - while (nNow2 - nNow < nFailTimeout) - { - xnOSGetHighResTimeStamp(&nNow2); - } - } - else - { - xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayReceive); - } - } - - return nRetVal; -} - -XnStatus ValidateReplyV26(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt16 nExpectedOpcode, XnUInt16 nRequestId, XnUInt16& nDataSize, XnUChar** pDataBuf) -{ - XnUInt16 nHeaderOffset = 0; - XnHostProtocolHeaderV26* pHeader = (XnHostProtocolHeaderV26*)pBuffer; - - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); - - while (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic && nHeaderOffset < nBufferSize-pDevicePrivateData->FWInfo.nProtocolHeaderSize-sizeof(XnHostProtocolReplyHeader)) - { - nHeaderOffset++; - pHeader = (XnHostProtocolHeaderV26*)(pBuffer+nHeaderOffset); - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); - } - - pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nId); - pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nOpcode); - pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nSize); - - if (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic) - { - return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; - } - - if (pHeader->nId != nRequestId) - { -// printf("Response ID (%d) not the same as request id (%d)\n", pHeader->nId, nRequestId); - return XN_STATUS_DEVICE_PROTOCOL_WRONG_ID; - } - - if (pHeader->nOpcode != nExpectedOpcode) - { -// printf("Unexpected opcode %d (expected: %d)\n", pHeader->nOpcode, nExpectedOpcode); - return XN_STATUS_DEVICE_PROTOCOL_WRONG_OPCODE; - } - // CRC? - // ... - - XnHostProtocolReplyHeader* pReply = (XnHostProtocolReplyHeader*)(pBuffer+nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize); - pReply->nErrorCode = XN_PREPARE_VAR16_IN_BUFFER(pReply->nErrorCode); - - if (pReply->nErrorCode != ACK) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Received NACK: %d", pReply->nErrorCode); - - switch (pReply->nErrorCode) - { - case NACK_INVALID_COMMAND: - return XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND; - case NACK_BAD_PACKET_CRC: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_CRC; - case NACK_BAD_PACKET_SIZE: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_SIZE; - case NACK_BAD_PARAMS: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS; - case NACK_BAD_COMMAND_SIZE: - return XN_STATUS_DEVICE_PROTOCOL_BAD_COMMAND_SIZE; - case NACK_NOT_READY: - return XN_STATUS_DEVICE_PROTOCOL_NOT_READY; - case NACK_UNKNOWN_ERROR: - default: - return XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR; - } - } - // Check reply length is reasonable for opcode - - nDataSize = pHeader->nSize - sizeof(XnHostProtocolReplyHeader)/sizeof(XnUInt16); - - if (pDataBuf) - *pDataBuf = pBuffer + nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader); - return XN_STATUS_OK; -} - -XnStatus ValidateReplyV25(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt16 nExpectedOpcode, XnUInt16 nRequestId, XnUInt16& nDataSize, XnUChar** pDataBuf) -{ - XnUInt16 nHeaderOffset = 0; - XnHostProtocolHeaderV25* pHeader = (XnHostProtocolHeaderV25*)pBuffer; - - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); - - while (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic && nHeaderOffset < nBufferSize-pDevicePrivateData->FWInfo.nProtocolHeaderSize-sizeof(XnHostProtocolReplyHeader)) - { - nHeaderOffset++; - pHeader = (XnHostProtocolHeaderV25*)(pBuffer+nHeaderOffset); - pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); - } - - pHeader->nCRC16 = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nCRC16); - pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nId); - pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nOpcode); - pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nSize); - - if (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic) - { - return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; - } - - if (pHeader->nId != nRequestId) - { - // printf("Response ID (%d) not the same as request id (%d)\n", pHeader->nId, nRequestId); - return XN_STATUS_DEVICE_PROTOCOL_WRONG_ID; - } - - if (pHeader->nOpcode != nExpectedOpcode) - { - // printf("Unexpected opcode %d (expected: %d)\n", pHeader->nOpcode, nExpectedOpcode); - return XN_STATUS_DEVICE_PROTOCOL_WRONG_OPCODE; - } - // CRC? - // ... - - XnHostProtocolReplyHeader* pReply = (XnHostProtocolReplyHeader*)(pBuffer+nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize); - - pReply->nErrorCode = XN_PREPARE_VAR16_IN_BUFFER(pReply->nErrorCode); - - if (pReply->nErrorCode != ACK) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Received NACK: %d", pReply->nErrorCode); - - switch (pReply->nErrorCode) - { - case NACK_INVALID_COMMAND: - return XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND; - case NACK_BAD_PACKET_CRC: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_CRC; - case NACK_BAD_PACKET_SIZE: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_SIZE; - case NACK_BAD_PARAMS: - return XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS; - case NACK_UNKNOWN_ERROR: - default: - return XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR; - } - } - // Check reply length is reasonable for opcode - - nDataSize = pHeader->nSize - sizeof(XnHostProtocolReplyHeader)/sizeof(XnUInt16); - - if (pDataBuf) - *pDataBuf = pBuffer + nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader); - return XN_STATUS_OK; -} - -XnUInt32 XnHostProtocolGetTimeOut(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nOpcode) -{ - if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeKeepAlive) - return XN_USB_HOST_PROTOCOL_TIMEOUT_KEEP_ALIVE; - else if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeGetVersion) - return XN_USB_HOST_PROTOCOL_TIMEOUT_GETVERSION; - else if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeSetParam) - return XN_USB_HOST_PROTOCOL_TIMEOUT_SETPARAM; - else - return XN_USB_HOST_PROTOCOL_TIMEOUT; -} - -XnUInt32 XnHostProtocolGetSetParamRecvTimeOut(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam) -{ - if (nParam == PARAM_IMAGE_FLICKER_DETECTION) - return pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker; - else if (nParam == PARAM_GENERAL_STREAM0_MODE) - return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode; - else if (nParam == PARAM_GENERAL_STREAM1_MODE) - return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode; - else if (nParam == PARAM_GENERAL_STREAM2_MODE) - return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode; - else - return 0; -} - -XnStatus XnHostProtocolGetRequestID(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt16* pnRequestId) -{ - XnUInt16 nRequestId; - - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) - { - nRequestId = ((XnHostProtocolHeaderV26*)(pBuffer))->nId; - } - else - { - nRequestId = ((XnHostProtocolHeaderV25*)(pBuffer))->nId; - } - - *pnRequestId = XN_PREPARE_VAR16_IN_BUFFER(nRequestId); - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolReceiveReply(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt16 nBufferSize, XnUInt32 nTimeOut, XnUInt16 nOpcode, XnUInt16 nRequestId, XnUInt32* pnReadBytes, XnUInt16* pnDataSize, XnUChar** ppRelevantBuffer, XnBool bForceBulk, XnUInt32 nRecvTimeout, XnUInt32 nFailTimeout) -{ - XnStatus rc = XN_STATUS_OK; - - XnUInt64 nStartWaitingTime; - xnOSGetTimeStamp(&nStartWaitingTime); - - while (TRUE) // loop until timeout expires - { - do // loop until right reply ID is received - { - // receive reply - if (nRecvTimeout != 0) - { - xnOSSleep(nRecvTimeout); - } - - rc = XnHostProtocolUSBReceive(pDevicePrivateData, pBuffer, pDevicePrivateData->FWInfo.nProtocolMaxPacketSize, *pnReadBytes, nTimeOut, bForceBulk, nFailTimeout); - XN_IS_STATUS_OK(rc); - - // Validate the reply - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) - { - rc = ValidateReplyV26(pDevicePrivateData, pBuffer, *pnReadBytes, nOpcode, nRequestId, *pnDataSize, ppRelevantBuffer); - } - else - { - rc = ValidateReplyV25(pDevicePrivateData, pBuffer, *pnReadBytes, nOpcode, nRequestId, *pnDataSize, ppRelevantBuffer); - } - } while (rc == XN_STATUS_DEVICE_PROTOCOL_WRONG_ID); - - XnUInt64 nNow; - xnOSGetTimeStamp(&nNow); - - if (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC) - { - return rc; - } - else if (rc == XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC && (nNow-nStartWaitingTime)>XN_RECEIVE_USB_DATA_TIMEOUT) - { - // Timeout expired - return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; - } - else if (rc == XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC) - { - // Timeout not expired yet - xnOSSleep(10); - } - else - { - // OK - break; - } - } - - return rc; -} - -XnStatus XnHostProtocolExecute(XnDevicePrivateData* pDevicePrivateData, - XnUChar* pBuffer, XnUInt16 nSize, XnUInt16 nOpcode, - XnUChar** ppRelevantBuffer, XnUInt16& nDataSize, XnUInt32 nRecvTimeout = 0) -{ - XnStatus rc; - XnUInt32 nRead; - XnUInt32 nFailTimeout = 0; - - XnBool bForceBulk = FALSE; - - if (nOpcode == OPCODE_INVALID) - { - return (XN_STATUS_DEVICE_PROTOCOL_UNSUPPORTED_OPCODE); - } - - XnUInt32 nTimeOut = XnHostProtocolGetTimeOut(pDevicePrivateData, nOpcode); - - // store request (in case we need to retry it) - XnUChar request[MAX_PACKET_SIZE]; - xnOSMemCopy(request, pBuffer, nSize); - - XnUInt16 nRequestId; - rc = XnHostProtocolGetRequestID(pDevicePrivateData, pBuffer, &nRequestId); - XN_IS_STATUS_OK(rc); - - XnUInt16 nRetriesLeft = XN_HOST_PROTOCOL_NOT_READY_RETRIES; - while (nRetriesLeft-- > 0) // loop until device is ready - { - rc = xnOSLockMutex(pDevicePrivateData->hExecuteMutex, XN_WAIT_INFINITE); - XN_IS_STATUS_OK(rc); - - // Sleep before sending the control - xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend); - - // Send request - rc = XnHostProtocolUSBSend(pDevicePrivateData, request, nSize, nRead, nTimeOut, bForceBulk); - if (rc != XN_STATUS_OK) - { - xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); - return rc; - } - - // Sleep before trying to read the reply - xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend); - - // receive reply - rc = XnHostProtocolReceiveReply(pDevicePrivateData, pBuffer, nSize, nTimeOut, nOpcode, nRequestId, &nRead, &nDataSize, ppRelevantBuffer, bForceBulk, nRecvTimeout, nFailTimeout); - - if (rc == XN_STATUS_DEVICE_PROTOCOL_NOT_READY || rc == XN_STATUS_OK) - { - XnStatus unlockRC = xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); - XN_IS_STATUS_OK(unlockRC); - } - else - { - xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); - return rc; - } - - if (rc == XN_STATUS_OK) - break; - - xnOSSleep(1000); - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Device not ready. %d more retries...", nRetriesLeft); - } - - XN_IS_STATUS_OK(rc); - - if (ppRelevantBuffer == NULL) - return XN_STATUS_OK; - - // Get rest of data - XnInt32 nDataRead = 0; - - XnInt32 nCur = nRead; // Read so far - - nRead -= (pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader)); // Data read so far - - while (nRead < nDataSize*2U) - { - XnUInt32 dummy = 0; - - rc = XnHostProtocolUSBReceive(pDevicePrivateData, pBuffer+nCur, pDevicePrivateData->FWInfo.nProtocolMaxPacketSize, dummy, nTimeOut, bForceBulk, 0); - if (rc != XN_STATUS_OK) - { - return rc; - } - - nCur += dummy; - nRead += dummy; - } - - nDataRead = nRead; - - return XN_STATUS_OK; -} - - -XnStatus XnHostProtocolGetVersion(XnDevicePrivateData* pDevicePrivateData, XnVersions& Version) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - XnUInt16 nDataSize; - XnVersions *pVersion = NULL; - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting hardware versions..."); - - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetVersion); - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetVersion, - (XnUChar**)(&pVersion), nDataSize); - if (rc != XN_STATUS_OK) - { - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_1); - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetVersion); - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetVersion, - (XnUChar**)(&pVersion), nDataSize); - - if (rc != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get version failed: %s", xnGetStatusString(rc)); - - return rc; - } - } - - xnOSMemCopy(&Version, pVersion, sizeof(XnVersions)); - - Version.nBuild = XN_PREPARE_VAR16_IN_BUFFER(Version.nBuild); - Version.nChip = XN_PREPARE_VAR32_IN_BUFFER(Version.nChip); - Version.nFPGA = XN_PREPARE_VAR16_IN_BUFFER(Version.nFPGA); - Version.nSystemVersion = XN_PREPARE_VAR16_IN_BUFFER(Version.nSystemVersion); - - *((XnUInt16*)&Version) = xnOSEndianSwapUINT16(*((XnUInt16*)pVersion)); - - if (Version.nMajor > 5 || (Version.nMajor == 5 && Version.nMinor > 3)) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Sensor version %d.%d is newer than latest known. Trying to use 5.3 protocol...", Version.nMajor, Version.nMinor); - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_3); - } - else if (Version.nMajor == 5 && Version.nMinor == 3) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_3); - else if (Version.nMajor == 5 && Version.nMinor == 2) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_2); - else if (Version.nMajor == 5 && Version.nMinor == 1) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); - else if (Version.nMajor == 5 && Version.nMinor == 0) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_0); - else if (Version.nMajor >= 4) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_4_0); - else if (Version.nMajor == 3 && Version.nMinor == 0) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_3_0); - else if (Version.nMajor == 1 && Version.nMinor == 2) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_2); - else if (Version.nMajor == 1 && Version.nMinor == 1) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_1); - else if (Version.nMajor == 0) - XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_0_17); - - Version.SDK.nMajor = XN_PS_MAJOR_VERSION; - Version.SDK.nMinor = XN_PS_MINOR_VERSION; - Version.SDK.nMaintenance = XN_PS_MAINTENANCE_VERSION; - Version.SDK.nBuild = XN_PS_BUILD_VERSION; - - if (Version.nFPGA == XN_FPGA_VER_FPDB_26) - { - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_FPDB_10; - } - else if (Version.nFPGA == XN_FPGA_VER_FPDB_25) - { - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_FPDB_10; - } - else if (Version.nFPGA == XN_FPGA_VER_CDB) - { - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_CDB_10; - } - else - { - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_UNKNOWN; - } - - if (Version.nChip == XN_CHIP_VER_PS1000) - { - pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_PS1000; - } - else if (Version.nChip == XN_CHIP_VER_PS1080) - { - pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_PS1080; - } - else - { - pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_UNKNOWN; - } - - if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_4_0) - { - pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_4_0; - } - else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_3_0) - { - pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_3_0; - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_RD_3; - } - else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_5_0 || pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_5_1) - { - pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_5_0; - pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_RD_5; - } - else - { - pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_2_0; - } - - Version.FWVer = pDevicePrivateData->FWInfo.nFWVer; - Version.HWVer = pDevicePrivateData->HWInfo.nHWVer; - Version.SensorVer = pDevicePrivateData->SensorInfo.nSensorVer; - Version.ChipVer = pDevicePrivateData->ChipInfo.nChipVer; - - if (Version.nMajor >= 5) - { - XnChar cpBuffer[XN_MAX_OS_NAME_LENGTH]; - sprintf(cpBuffer, "%x", Version.nBuild); - Version.nBuild = atoi(cpBuffer); - } - - if ((Version.nMajor >= 5) && (Version.nMinor >= 3) && (Version.nBuild >= 16)) - { - pDevicePrivateData->FWInfo.nUSBDelayReceive = 1; - pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend = 0; - pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend = 0; - pDevicePrivateData->FWInfo.nUSBDelaySoftReset = 1; - pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 1; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode = 1; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode = 1; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode = 1; - } - else - { - pDevicePrivateData->FWInfo.nUSBDelayReceive = 100; - pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend = 1; - pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend = 10; - pDevicePrivateData->FWInfo.nUSBDelaySoftReset = 800; - pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 3000; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode = 1; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode = 300; - pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode = 1; - - if ((Version.nMajor == 5) && (Version.nMinor == 3) && (Version.nBuild == 15)) - { - pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 300; - } - } - - xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Hardware versions: FW=%d.%d.%d (%d) HW=%d Chip=%d Sensor=%d SYS=%d", Version.nMajor, Version.nMinor, Version.nBuild, Version.FWVer, Version.HWVer, Version.ChipVer, Version.SensorVer, Version.nSystemVersion); - - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolKeepAlive(XnDevicePrivateData* pDevicePrivateData) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Requesting KeepAlive..."); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeKeepAlive); - - XnUInt16 nDataSize; - - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeKeepAlive, - NULL, nDataSize); - - if (rc == XN_STATUS_OK) - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Got KeepAlive Reply."); - else - xnLogError(XN_MASK_SENSOR_PROTOCOL, "KeepAlive failed: %s", xnGetStatusString(rc)); - - return rc; -} - - -XnStatus XnHostProtocolGetParam(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16& nValue) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - -// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Getting Parameter [%d]...", nParam); - - *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nParam); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetParam); - - XnUInt16 nDataSize; - XnUInt16* pValue = NULL; - - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetParam, - (XnUChar**)(&pValue), nDataSize); - if (rc != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed getting [%d]: %s", nParam, xnGetStatusString(rc)); - return rc; - } - -// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Param[%d] = %d", nParam, *pValue); - nValue = XN_PREPARE_VAR16_IN_BUFFER(*pValue); - - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolSetParam(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16 nValue) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - -// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Setting Parameter [%d] to %d", nParam, nValue); - - *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nParam); - *(((XnUInt16*)pDataBuf)+1) = XN_PREPARE_VAR16_IN_BUFFER(nValue); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16)*2, pDevicePrivateData->FWInfo.nOpcodeSetParam); - - XnUInt16 nDataSize; - - XnInt32 nTimesLeft = 5; - XnStatus rc = XN_STATUS_ERROR; - while (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS && - rc != XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND && nTimesLeft > 0) - { - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16)*2, pDevicePrivateData->FWInfo.nOpcodeSetParam, - NULL, nDataSize, XnHostProtocolGetSetParamRecvTimeOut(pDevicePrivateData, nParam)); - nTimesLeft--; - - if (rc != XN_STATUS_OK) - { - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Retrying to set the param... rc=%d", rc); - } - } - - if (rc != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed setting [%d] to [%d]: %s", nParam, nValue, xnGetStatusString(rc)); - } - else - { -// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Done."); - } - - return rc; -} - -void XnHostPrototcolAdjustFixedParamsV26(XnFixedParamsV26* pFixedParamsV26, XnFixedParams* pFixedParams) -{ - // the only difference from V2.6 to V3.0 is the 4 last parameters - xnOSMemCopy(pFixedParams, pFixedParamsV26, sizeof(XnFixedParamsV26)); - pFixedParams->nUseExtPhy = pFixedParamsV26->nUseExtPhy; - pFixedParams->bProjectorProtectionEnabled = FALSE; - pFixedParams->nProjectorDACOutputVoltage = FALSE; - pFixedParams->nTecEmitterDelay = pFixedParamsV26->nTecEmitterDelay; -} - -void XnHostPrototcolAdjustFixedParamsV20(XnFixedParamsV20* pFixedParamsV20, XnFixedParams* pFixedParams) -{ - // the only difference from V2.0 to V2.6 is the addition of nUseExtPhy - XnFixedParamsV26 fixedParamsV26; - xnOSMemCopy(&fixedParamsV26, pFixedParamsV20, sizeof(XnFixedParamsV20)); - - // now adjust from V2.6 to current - XnHostPrototcolAdjustFixedParamsV26(&fixedParamsV26, pFixedParams); -} - -XnStatus XnHostProtocolGetFixedParams(XnDevicePrivateData* pDevicePrivateData, XnFixedParams& FixedParams) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - XnUChar* pRelevantBuffer; - XnUInt16 nFixedParamSize = 0; - - XnChar FixedParamsBuffer[2048] = {0}; - XnChar* pData = FixedParamsBuffer; - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting the fixed params..."); - - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_3_0) - { - nFixedParamSize = sizeof(XnFixedParams); - } - else if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_1) - { - nFixedParamSize = sizeof(XnFixedParamsV26); - } - else // v0.17 - { - nFixedParamSize = sizeof(XnFixedParamsV20); - } - - xnOSMemSet(&FixedParams, 0, sizeof(XnFixedParams)); - - XnInt16 nDataRead = 0; - - XnStatus rc; - while (nDataRead < nFixedParamSize) - { - *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nDataRead/sizeof(XnUInt32))); - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetFixedParams); - - XnUInt16 nDataSize; - - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetFixedParams, - &pRelevantBuffer, nDataSize); - - if (rc != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get fixed params failed: %s", xnGetStatusString(rc)); - - return rc; - } - - XnUInt32 nReadNow = nDataSize*sizeof(XnUInt16); - if (nReadNow == 0) - { - break; - } - - xnOSMemCopy(pData + nDataRead, pRelevantBuffer, nReadNow); - - nDataRead += nReadNow; - } - - for (XnUInt32 i = 0; i < nFixedParamSize/sizeof(XnUInt32); i ++) - { - XnUInt32 temp = *((XnUInt32*)(&FixedParams)+i); - *((XnUInt32*)(&FixedParams)+i) = XN_PREPARE_VAR32_IN_BUFFER(temp); - } - - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_3_0) - { - xnOSMemCopy(&FixedParams, FixedParamsBuffer, sizeof(XnFixedParams)); - } - else if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_1) - { - XnFixedParamsV26 fixedParamsV26; - xnOSMemCopy(&fixedParamsV26, FixedParamsBuffer, nFixedParamSize); - XnHostPrototcolAdjustFixedParamsV26(&fixedParamsV26, &FixedParams); - } - else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_0_17) - { - XnFixedParamsV20 fixedParamsV20; - xnOSMemCopy(&fixedParamsV20, FixedParamsBuffer, nFixedParamSize); - XnHostPrototcolAdjustFixedParamsV20(&fixedParamsV20, &FixedParams); - } - - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolGetMode(XnDevicePrivateData* pDevicePrivateData, XnUInt16& nMode) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetMode); - - XnUInt16 nDataSize; - XnUInt16* pMode = NULL; - - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetMode, - (XnUChar**)(&pMode), nDataSize); - if (rc != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get mode failed: %s", xnGetStatusString(rc)); - - return rc; - } - nMode = XN_PREPARE_VAR16_IN_BUFFER(*pMode); - - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolReset(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nResetType) -{ - XnStatus rc = XN_STATUS_OK; - - if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_0_17) - { - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nResetType); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeReset); - - XnUInt16 nDataSize; - - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeReset, - NULL, nDataSize); - - // Power reset can't fail, and device won't have time to send ACK. - if (nResetType == XN_RESET_TYPE_POWER) - rc = XN_STATUS_OK; - - return rc; - } - else - { - XnUInt16 nActualValue; - switch (nResetType) - { - case XN_RESET_TYPE_POWER: - nActualValue = XN_HOST_PROTOCOL_MODE_REBOOT; - break; - case XN_RESET_TYPE_SOFT: - { - // also kill streams before (in FW < 5.2) - if (pDevicePrivateData->FWInfo.nFWVer < XN_SENSOR_FW_VER_5_2) - { - XnSensorFirmwareParams* pParams = pDevicePrivateData->pSensor->GetFirmware()->GetParams(); - rc = pParams->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); - XN_IS_STATUS_OK(rc); - rc = pParams->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); - XN_IS_STATUS_OK(rc); - rc = pParams->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); - XN_IS_STATUS_OK(rc); - } - } - - nActualValue = XN_HOST_PROTOCOL_MODE_SOFT_RESET; - break; - case XN_RESET_TYPE_SOFT_FIRST: - nActualValue = XN_HOST_PROTOCOL_MODE_SOFT_RESET; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - return XnHostProtocolSetMode(pDevicePrivateData, nActualValue); - } -} - -XnStatus XnHostProtocolSetMode(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nMode) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nMode); - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Setting mode to %d...", nMode); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeSetMode); - - XnUInt16 nDataSize; - - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeSetMode, - NULL, nDataSize); - - // Patch: always return OK when switching modes (since the firmware is changing there is nobody to ACK the request...) - return XN_STATUS_OK; -} - - -#pragma pack (push, 1) -typedef struct XnAlgorithmParamRequest -{ - XnUInt16 nParamID; - XnUInt16 nFormat; - XnUInt16 nResolution; - XnUInt16 nFPS; - XnUInt16 nOffset; -} XnAlgorithmParamRequest; - -typedef struct XnAlgorithmParamRequestV4 -{ - XnUInt8 nResolution; - XnUInt8 nFPS; - XnUInt8 nFormat; - XnUInt8 nParamID; - XnUInt16 nOffset; -} XnAlgorithmParamRequestV4; -#pragma pack (pop) - -XnStatus XnHostProtocolAlgorithmParams(XnDevicePrivateData* pDevicePrivateData, - XnHostProtocolAlgorithmType eAlgorithmType, - void* pAlgorithmInformation, XnUInt16 nAlgInfoSize, XnResolutions nResolution, XnUInt16 nFPS) -{ - XnChar* pData = (XnChar*)pAlgorithmInformation; - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - XnUChar* pRelevantBuffer; - - XnInt16 nDataRead = 0; - XnUInt16 nRequestSize = 0; - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting algorithm params 0x%x for resolution %d and fps %d....", eAlgorithmType, nResolution, nFPS); - - XnStatus rc; - while (nDataRead < nAlgInfoSize) - { - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1) - { - XnAlgorithmParamRequest* pRequest = (XnAlgorithmParamRequest*)pDataBuf; - pRequest->nParamID = XN_PREPARE_VAR16_IN_BUFFER(eAlgorithmType); - pRequest->nFormat = 0; - pRequest->nResolution = XN_PREPARE_VAR16_IN_BUFFER(nResolution); - pRequest->nFPS = XN_PREPARE_VAR16_IN_BUFFER(nFPS); - pRequest->nOffset = XN_PREPARE_VAR16_IN_BUFFER(nDataRead / sizeof(XnUInt16)); - nRequestSize = sizeof(XnAlgorithmParamRequest); - } - else - { - XnAlgorithmParamRequestV4* pRequest = (XnAlgorithmParamRequestV4*)pDataBuf; - pRequest->nParamID = eAlgorithmType; - pRequest->nFormat = 0; - pRequest->nResolution = nResolution; - pRequest->nFPS = 0; - pRequest->nOffset = XN_PREPARE_VAR16_IN_BUFFER(nDataRead / sizeof(XnUInt16)); - nRequestSize = sizeof(XnAlgorithmParamRequestV4); - } - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, nRequestSize, pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams); - - XnUInt16 nDataSize; - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+nRequestSize, pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams, - &pRelevantBuffer, nDataSize); - - - if (rc != XN_STATUS_OK) - return rc; - - XnUInt32 nReadNow = nDataSize*sizeof(XnUInt16); - if (nReadNow == 0) - { - break; - } - - xnOSMemCopy(pData + nDataRead, pRelevantBuffer, nReadNow); - - nDataRead += nReadNow; - } - - if (nDataRead != nAlgInfoSize) - { - XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_INVALID_RESPONSE_SIZE, XN_MASK_SENSOR_PROTOCOL, "Failed getting algorithm params: expected %u bytes, but got only %u", nAlgInfoSize, nDataRead); - } - - return XN_STATUS_OK; -} - - -XnStatus XnHostProtocolSetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate nSampleRate) -{ - EA2d_SampleRate nSample; - - switch (nSampleRate) - { - case XN_SAMPLE_RATE_8K: - nSample = A2D_SAMPLE_RATE_8KHZ; - break; - case XN_SAMPLE_RATE_11K: - nSample = A2D_SAMPLE_RATE_11KHZ; - break; - case XN_SAMPLE_RATE_12K: - nSample = A2D_SAMPLE_RATE_12KHZ; - break; - case XN_SAMPLE_RATE_16K: - nSample = A2D_SAMPLE_RATE_16KHZ; - break; - case XN_SAMPLE_RATE_22K: - nSample = A2D_SAMPLE_RATE_22KHZ; - break; - case XN_SAMPLE_RATE_24K: - nSample = A2D_SAMPLE_RATE_24KHZ; - break; - case XN_SAMPLE_RATE_32K: - nSample = A2D_SAMPLE_RATE_32KHZ; - break; - case XN_SAMPLE_RATE_44K: - nSample = A2D_SAMPLE_RATE_44KHZ; - break; - case XN_SAMPLE_RATE_48K: - nSample = A2D_SAMPLE_RATE_48KHZ; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - return XnHostProtocolSetParam(pDevicePrivateData, PARAM_AUDIO_SAMPLE_RATE, nSample); -} - -XnStatus XnHostProtocolGetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate* pSampleRate) -{ - XnUInt16 nValue; - XnHostProtocolGetParam(pDevicePrivateData, PARAM_AUDIO_SAMPLE_RATE, nValue); - XnSampleRate nSample; - - switch (nValue) - { - case A2D_SAMPLE_RATE_8KHZ: - nSample = XN_SAMPLE_RATE_8K; - break; - case A2D_SAMPLE_RATE_11KHZ: - nSample = XN_SAMPLE_RATE_11K; - break; - case A2D_SAMPLE_RATE_12KHZ: - nSample = XN_SAMPLE_RATE_12K; - break; - case A2D_SAMPLE_RATE_16KHZ: - nSample = XN_SAMPLE_RATE_16K; - break; - case A2D_SAMPLE_RATE_22KHZ: - nSample = XN_SAMPLE_RATE_22K; - break; - case A2D_SAMPLE_RATE_24KHZ: - nSample = XN_SAMPLE_RATE_24K; - break; - case A2D_SAMPLE_RATE_32KHZ: - nSample = XN_SAMPLE_RATE_32K; - break; - case A2D_SAMPLE_RATE_44KHZ: - nSample = XN_SAMPLE_RATE_44K; - break; - case A2D_SAMPLE_RATE_48KHZ: - nSample = XN_SAMPLE_RATE_48K; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - *pSampleRate = nSample; - - return (XN_STATUS_OK); -} - - -XnStatus XnHostProtocolSetMultipleParams(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nNumOfParams, XnInnerParamData* anParams) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - XnUInt16* pCurData = (XnUInt16*)pDataBuf; - for (XnUInt16 nIndex = 0; nIndex < nNumOfParams; ++nIndex) - { - *pCurData++ = XN_PREPARE_VAR16_IN_BUFFER(anParams[nIndex].nParam); - *pCurData++ = XN_PREPARE_VAR16_IN_BUFFER(anParams[nIndex].nValue); - } - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16)*nNumOfParams*2, pDevicePrivateData->FWInfo.nOpcodeSetParam); - - XnUInt16 nDataSize; - - XnInt32 nTimesLeft = 5; - XnStatus rc = XN_STATUS_ERROR; - while (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS && - rc != XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND && nTimesLeft > 0) - { - rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16)*nNumOfParams*2, pDevicePrivateData->FWInfo.nOpcodeSetParam, - NULL, nDataSize); - nTimesLeft--; - } - - if (rc != XN_STATUS_OK) - xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed: %s", xnGetStatusString(rc)); - - return rc; -} - - -XnStatus XnHostProtocolSetIRCropping(XnDevicePrivateData* pDevicePrivateData, XnCropping* pCropping) -{ - XnStatus rc = XN_STATUS_OK; - - if (pCropping->bEnabled) - { - XnInnerParamData anParams[4]; - XnUInt16 nIndex = 0; - - anParams[nIndex].nParam = PARAM_IR_CROP_SIZE_X; - anParams[nIndex].nValue = pCropping->nXSize; - nIndex++; - anParams[nIndex].nParam = PARAM_IR_CROP_SIZE_Y; - anParams[nIndex].nValue = pCropping->nYSize; - nIndex++; - anParams[nIndex].nParam = PARAM_IR_CROP_OFFSET_X; - anParams[nIndex].nValue = pCropping->nXOffset; - nIndex++; - anParams[nIndex].nParam = PARAM_IR_CROP_OFFSET_Y; - anParams[nIndex].nValue = pCropping->nYOffset; - - rc = XnHostProtocolSetMultipleParams(pDevicePrivateData, 4, anParams); - if (rc != XN_STATUS_OK) - return rc; - } - - // commit - rc = XnHostProtocolSetParam(pDevicePrivateData, PARAM_IR_CROP_ENABLE, pCropping->bEnabled); - - return rc; -} - - -XnStatus XnDeviceSensorGetDepthAGCParams(XnUInt16 nBin, XnUInt16* pnMinParam, XnUInt16* pnMaxParam) -{ - switch (nBin) - { - case 0: - *pnMinParam = PARAM_DEPTH_AGC_BIN0_LOW; - *pnMaxParam = PARAM_DEPTH_AGC_BIN0_HIGH; - break; - case 1: - *pnMinParam = PARAM_DEPTH_AGC_BIN1_LOW; - *pnMaxParam = PARAM_DEPTH_AGC_BIN1_HIGH; - break; - case 2: - *pnMinParam = PARAM_DEPTH_AGC_BIN2_LOW; - *pnMaxParam = PARAM_DEPTH_AGC_BIN2_HIGH; - break; - case 3: - *pnMinParam = PARAM_DEPTH_AGC_BIN3_LOW; - *pnMaxParam = PARAM_DEPTH_AGC_BIN3_HIGH; - break; - default: - return XN_STATUS_DEVICE_BAD_PARAM; - } - - return XN_STATUS_OK; -} - -XnStatus XnHostProtocolSetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16 nMinShift, XnUInt16 nMaxShift) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt16 nMinParam; - XnUInt16 nMaxParam; - - nRetVal = XnDeviceSensorGetDepthAGCParams(nBin, &nMinParam, &nMaxParam); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnHostProtocolSetParam(pDevicePrivateData, nMinParam, nMinShift); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnHostProtocolSetParam(pDevicePrivateData, nMaxParam, nMaxShift); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnHostProtocolGetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16* pnMinShift, XnUInt16* pnMaxShift) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt16 nMinParam; - XnUInt16 nMaxParam; - - nRetVal = XnDeviceSensorGetDepthAGCParams(nBin, &nMinParam, &nMaxParam); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnHostProtocolGetParam(pDevicePrivateData, nMinParam, *pnMinShift); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnHostProtocolGetParam(pDevicePrivateData, nMaxParam, *pnMaxShift); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -#pragma pack (push, 1) - -typedef struct XnVSyncRequest -{ - XnUInt16 nUnits; - XnUInt16 nCmosID; - XnUInt16 nNumberOfFrames; -} XnVSyncRequest; - -#pragma pack (pop) - -XnStatus XnHostProtocolSetCmosBlanking(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nUnits, XnCMOSType nCMOSID, XnUInt16 nNumberOfFrames) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - XnUInt32 nRequestSize; - - if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1) - { - XnVSyncRequest* pRequest = (XnVSyncRequest*)pDataBuf; - pRequest->nUnits = XN_PREPARE_VAR16_IN_BUFFER(nUnits); - pRequest->nCmosID = XN_PREPARE_VAR16_IN_BUFFER(nCMOSID); - pRequest->nNumberOfFrames = XN_PREPARE_VAR16_IN_BUFFER(nNumberOfFrames); - nRequestSize = sizeof(XnVSyncRequest); - } - else - { - XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED, XN_MASK_SENSOR_PROTOCOL, "Set Blanking is not supported by this firmware!"); - } - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Chaning CMOS %d Blanking to %hd (NumberOfFrames=%hu)...", nCMOSID, nUnits, nNumberOfFrames); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, nRequestSize, pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking); - - XnUInt16 nDataSize; - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize + nRequestSize, pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking, - NULL, nDataSize); - - if (rc != XN_STATUS_OK) - { - XN_LOG_WARNING_RETURN(rc, XN_MASK_SENSOR_PROTOCOL, "Failed changing CMOS %d Blanking to %hd (NumberOfFrames=%hu): %s", nCMOSID, nUnits, nNumberOfFrames, xnGetStatusString(rc)); - } - - return (XN_STATUS_OK); -} - -#pragma pack (push, 1) - -typedef struct XnGetCmosBlankingRequest -{ - XnUInt16 nCmosID; -} XnGetCmosBlankingRequest; - -typedef struct XnGetCmosBlankingReply -{ - XnUInt32 nUnits; -} XnGetCmosBlankingReply; - -#pragma pack (pop) - -XnStatus XnHostProtocolGetCmosBlanking(XnDevicePrivateData* pDevicePrivateData, XnCMOSType nCMOSID, XnUInt16* pnLines) -{ - XnUChar buffer[MAX_PACKET_SIZE] = {0}; - XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; - - XnGetCmosBlankingRequest* pRequest = (XnGetCmosBlankingRequest*)pDataBuf; - pRequest->nCmosID = nCMOSID; - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting Cmos %d VBlanking...", nCMOSID); - - XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnGetCmosBlankingRequest), pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking); - - XnGetCmosBlankingReply* pReply; - XnUInt16 nDataSize; - XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, - buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize + sizeof(XnGetCmosBlankingRequest), pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking, - (XnUChar**)&pReply, nDataSize); - - if (rc != XN_STATUS_OK) - { - XN_LOG_WARNING_RETURN(rc, XN_MASK_SENSOR_PROTOCOL, "Failed getting Cmos %d Blanking: %s", nCMOSID, xnGetStatusString(rc)); - } - - xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Cmos %d VBlanking: %u", nCMOSID, pReply->nUnits); - - *pnLines = pReply->nUnits; - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#include "XnDeviceSensorProtocol.h" +#include "XnHostProtocol.h" +#include +#include +#include "XnSensorDepthStream.h" +#include "XnSensor.h" +#include + +// Control Protocol +#include "XnParams.h" + +#define XN_RECEIVE_USB_DATA_TIMEOUT 20000 +#define XN_USB_HOST_PROTOCOL_TIMEOUT 5000 +#define XN_USB_HOST_PROTOCOL_TIMEOUT_KEEP_ALIVE 5000 +#define XN_USB_HOST_PROTOCOL_TIMEOUT_GETVERSION 5000 +#define XN_USB_HOST_PROTOCOL_TIMEOUT_SETPARAM 5000 + + +#define XN_USB_HOST_PROTOCOL_SEND_RETRIES 5 +#define XN_HOST_PROTOCOL_NOT_READY_RETRIES 3 + +#define XN_PROTOCOL_MAX_PACKET_SIZE_V5_0 512 +#define XN_PROTOCOL_MAX_PACKET_SIZE_V0_17 64 + +#define MAX_PACKET_SIZE 512 + +XnStatus XnHostProtocolInitFWParams(XnDevicePrivateData* pDevicePrivateData, XnFWVer nFWVer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nFWVer) + { + case XN_SENSOR_FW_VER_5_3: + nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_2); + XN_IS_STATUS_OK(nRetVal); + + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + break; + + case XN_SENSOR_FW_VER_5_2: + nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); + XN_IS_STATUS_OK(nRetVal); + + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + break; + + case XN_SENSOR_FW_VER_5_1: + nRetVal = XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_0); + XN_IS_STATUS_OK(nRetVal); + + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_GET_CMOS_BLANKING; + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + break; + + case XN_SENSOR_FW_VER_5_0: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V5_0; + pDevicePrivateData->FWInfo.bAudioSupported = TRUE; + + pDevicePrivateData->FWInfo.bMirrorSupported = TRUE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_GET_MODE; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_SET_MODE; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_ALGORITM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_SET_CMOS_BLANKING; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + + break; + + case XN_SENSOR_FW_VER_4_0: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; + pDevicePrivateData->FWInfo.bAudioSupported = FALSE; + pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V400_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V400_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V400_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V400_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V400_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V400_GET_MODE; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V400_SET_MODE; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V400_ALGORITM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + break; + case XN_SENSOR_FW_VER_3_0: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; + pDevicePrivateData->FWInfo.bAudioSupported = TRUE; + pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V300_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V300_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V300_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V300_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V300_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V300_GET_MODE; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V300_SET_MODE; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V300_ALGORITM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + break; + case XN_SENSOR_FW_VER_1_2: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_26; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_26; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV26); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; + pDevicePrivateData->FWInfo.bAudioSupported = FALSE; + pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V110_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V110_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V110_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V110_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V110_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V110_GET_MODE; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V110_SET_MODE; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V110_ALGORITHM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + break; + case XN_SENSOR_FW_VER_1_1: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_25; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_25; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV25); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; + pDevicePrivateData->FWInfo.bAudioSupported = FALSE; + pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V110_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V110_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V110_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V110_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V110_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_V110_GET_MODE; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_V110_SET_MODE; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V110_ALGORITHM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + break; + case XN_SENSOR_FW_VER_0_17: + pDevicePrivateData->FWInfo.nFWVer = nFWVer; + pDevicePrivateData->FWInfo.nFWMagic = XN_FW_MAGIC_25; + pDevicePrivateData->FWInfo.nHostMagic = XN_HOST_MAGIC_25; + pDevicePrivateData->FWInfo.nProtocolHeaderSize = sizeof(XnHostProtocolHeaderV25); + pDevicePrivateData->FWInfo.nProtocolMaxPacketSize = XN_PROTOCOL_MAX_PACKET_SIZE_V0_17; + pDevicePrivateData->FWInfo.bAudioSupported = FALSE; + pDevicePrivateData->FWInfo.bMirrorSupported = FALSE; + + pDevicePrivateData->FWInfo.nOpcodeGetVersion = OPCODE_V017_GET_VERSION; + pDevicePrivateData->FWInfo.nOpcodeKeepAlive = OPCODE_V017_KEEP_ALIVE; + pDevicePrivateData->FWInfo.nOpcodeGetParam = OPCODE_V017_GET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeSetParam = OPCODE_V017_SET_PARAM; + pDevicePrivateData->FWInfo.nOpcodeGetFixedParams = OPCODE_V017_GET_FIXED_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeGetMode = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeSetMode = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams = OPCODE_V017_ALGORITM_PARAMS; + pDevicePrivateData->FWInfo.nOpcodeReset = OPCODE_V017_RESET; + pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking = OPCODE_INVALID; + pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking = OPCODE_INVALID; + + break; + default: + return (XN_STATUS_IO_DEVICE_WRONG_VERSION); + } + + pDevicePrivateData->FWInfo.nCurrMode = XN_MODE_PS; + + return (XN_STATUS_OK); +} + +XnStatus XnHostProtocolInitHeader(XnDevicePrivateData* pDevicePrivateData, void* pBuffer, void* pDataBuf, XnUInt32 nSize, XnUInt16 nOpcode) +{ + static XnUInt16 nId = 0; + + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) + { + XnHostProtocolHeaderV26* pHeader = (XnHostProtocolHeaderV26*)pBuffer; + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nHostMagic); + pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nSize/sizeof(XnUInt16))); + pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(nOpcode); + pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(nId++); + } + else + { + XnHostProtocolHeaderV25* pHeader = (XnHostProtocolHeaderV25*)pBuffer; + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pDevicePrivateData->FWInfo.nHostMagic); + pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nSize/sizeof(XnUInt16))); + pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(nOpcode); + pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(nId++); + pHeader->nCRC16 = XN_PREPARE_VAR16_IN_BUFFER(0); + } + + return (XN_STATUS_OK); +} + +XnStatus XnHostProtocolUSBSend(XnDevicePrivateData* pDevicePrivateData, + XnUChar* pBuffer, XnUInt16 nSize, XnUInt32& nRead, XnUInt32 nTimeOut, XnBool bForceBulk) +{ + XnStatus nRetVal; + + XnUsbControlConnection* pCtrlConnection = &pDevicePrivateData->SensorHandle.ControlConnection; + + XnUInt32 nCounter = XN_USB_HOST_PROTOCOL_SEND_RETRIES; + while (nCounter-- != 0) + { + if (pCtrlConnection->bIsBulk || bForceBulk) + nRetVal = xnUSBWriteEndPoint(pCtrlConnection->ControlOutConnectionEp, pBuffer, nSize, nTimeOut); + else + { + nRetVal = xnUSBSendControl(pDevicePrivateData->SensorHandle.USBDevice, XN_USB_CONTROL_TYPE_VENDOR, 0, 0, 0, pBuffer, nSize, nTimeOut); + } + + if (nRetVal != XN_STATUS_USB_TRANSFER_TIMEOUT && nRetVal != XN_STATUS_USB_TRANSFER_STALL) + break; + + xnOSSleep(100); + } + + return nRetVal; +} + +XnStatus XnHostProtocolUSBReceive(XnDevicePrivateData* pDevicePrivateData, + XnUChar* pBuffer, XnUInt nSize, XnUInt32& nRead, XnUInt32 nTimeOut, XnBool bForceBulk, XnUInt32 nFailTimeout) +{ + XnStatus nRetVal; + XnUInt64 nMaxTime; + XnUInt64 nCurrTime; + + XnUsbControlConnection* pCtrlConnection = &pDevicePrivateData->SensorHandle.ControlConnection; + + xnOSGetHighResTimeStamp(&nMaxTime); + nMaxTime += (nTimeOut * 1000); + + while (TRUE) + { + xnOSGetHighResTimeStamp(&nCurrTime); + if (nCurrTime > nMaxTime) + { + return (XN_STATUS_USB_TRANSFER_TIMEOUT); + } + + if (pCtrlConnection->bIsBulk || bForceBulk) + nRetVal = xnUSBReadEndPoint(pCtrlConnection->ControlInConnectionEp, pBuffer, nSize, &nRead, nTimeOut); + else + nRetVal = xnUSBReceiveControl(pDevicePrivateData->SensorHandle.USBDevice, XN_USB_CONTROL_TYPE_VENDOR, 0, 0, 0, pBuffer, nSize, &nRead, nTimeOut); + + if (nRetVal != XN_STATUS_USB_TRANSFER_TIMEOUT && nRetVal != XN_STATUS_USB_TRANSFER_STALL && nRetVal != XN_STATUS_USB_NOT_ENOUGH_DATA) + { + break; + } + + if (nFailTimeout != 0) + { + XnUInt64 nNow; + XnUInt64 nNow2; + xnOSGetHighResTimeStamp(&nNow); + xnOSGetHighResTimeStamp(&nNow2); + while (nNow2 - nNow < nFailTimeout) + { + xnOSGetHighResTimeStamp(&nNow2); + } + } + else + { + xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayReceive); + } + } + + return nRetVal; +} + +XnStatus ValidateReplyV26(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt16 nExpectedOpcode, XnUInt16 nRequestId, XnUInt16& nDataSize, XnUChar** pDataBuf) +{ + XnUInt16 nHeaderOffset = 0; + XnHostProtocolHeaderV26* pHeader = (XnHostProtocolHeaderV26*)pBuffer; + + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); + + while (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic && nHeaderOffset < nBufferSize-pDevicePrivateData->FWInfo.nProtocolHeaderSize-sizeof(XnHostProtocolReplyHeader)) + { + nHeaderOffset++; + pHeader = (XnHostProtocolHeaderV26*)(pBuffer+nHeaderOffset); + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); + } + + pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nId); + pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nOpcode); + pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nSize); + + if (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic) + { + return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; + } + + if (pHeader->nId != nRequestId) + { +// printf("Response ID (%d) not the same as request id (%d)\n", pHeader->nId, nRequestId); + return XN_STATUS_DEVICE_PROTOCOL_WRONG_ID; + } + + if (pHeader->nOpcode != nExpectedOpcode) + { +// printf("Unexpected opcode %d (expected: %d)\n", pHeader->nOpcode, nExpectedOpcode); + return XN_STATUS_DEVICE_PROTOCOL_WRONG_OPCODE; + } + // CRC? + // ... + + XnHostProtocolReplyHeader* pReply = (XnHostProtocolReplyHeader*)(pBuffer+nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize); + pReply->nErrorCode = XN_PREPARE_VAR16_IN_BUFFER(pReply->nErrorCode); + + if (pReply->nErrorCode != ACK) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Received NACK: %d", pReply->nErrorCode); + + switch (pReply->nErrorCode) + { + case NACK_INVALID_COMMAND: + return XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND; + case NACK_BAD_PACKET_CRC: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_CRC; + case NACK_BAD_PACKET_SIZE: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_SIZE; + case NACK_BAD_PARAMS: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS; + case NACK_BAD_COMMAND_SIZE: + return XN_STATUS_DEVICE_PROTOCOL_BAD_COMMAND_SIZE; + case NACK_NOT_READY: + return XN_STATUS_DEVICE_PROTOCOL_NOT_READY; + case NACK_UNKNOWN_ERROR: + default: + return XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR; + } + } + // Check reply length is reasonable for opcode + + nDataSize = pHeader->nSize - sizeof(XnHostProtocolReplyHeader)/sizeof(XnUInt16); + + if (pDataBuf) + *pDataBuf = pBuffer + nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader); + return XN_STATUS_OK; +} + +XnStatus ValidateReplyV25(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt16 nExpectedOpcode, XnUInt16 nRequestId, XnUInt16& nDataSize, XnUChar** pDataBuf) +{ + XnUInt16 nHeaderOffset = 0; + XnHostProtocolHeaderV25* pHeader = (XnHostProtocolHeaderV25*)pBuffer; + + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); + + while (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic && nHeaderOffset < nBufferSize-pDevicePrivateData->FWInfo.nProtocolHeaderSize-sizeof(XnHostProtocolReplyHeader)) + { + nHeaderOffset++; + pHeader = (XnHostProtocolHeaderV25*)(pBuffer+nHeaderOffset); + pHeader->nMagic = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nMagic); + } + + pHeader->nCRC16 = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nCRC16); + pHeader->nId = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nId); + pHeader->nOpcode = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nOpcode); + pHeader->nSize = XN_PREPARE_VAR16_IN_BUFFER(pHeader->nSize); + + if (pHeader->nMagic != pDevicePrivateData->FWInfo.nFWMagic) + { + return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; + } + + if (pHeader->nId != nRequestId) + { + // printf("Response ID (%d) not the same as request id (%d)\n", pHeader->nId, nRequestId); + return XN_STATUS_DEVICE_PROTOCOL_WRONG_ID; + } + + if (pHeader->nOpcode != nExpectedOpcode) + { + // printf("Unexpected opcode %d (expected: %d)\n", pHeader->nOpcode, nExpectedOpcode); + return XN_STATUS_DEVICE_PROTOCOL_WRONG_OPCODE; + } + // CRC? + // ... + + XnHostProtocolReplyHeader* pReply = (XnHostProtocolReplyHeader*)(pBuffer+nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize); + + pReply->nErrorCode = XN_PREPARE_VAR16_IN_BUFFER(pReply->nErrorCode); + + if (pReply->nErrorCode != ACK) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Received NACK: %d", pReply->nErrorCode); + + switch (pReply->nErrorCode) + { + case NACK_INVALID_COMMAND: + return XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND; + case NACK_BAD_PACKET_CRC: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_CRC; + case NACK_BAD_PACKET_SIZE: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PACKET_SIZE; + case NACK_BAD_PARAMS: + return XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS; + case NACK_UNKNOWN_ERROR: + default: + return XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR; + } + } + // Check reply length is reasonable for opcode + + nDataSize = pHeader->nSize - sizeof(XnHostProtocolReplyHeader)/sizeof(XnUInt16); + + if (pDataBuf) + *pDataBuf = pBuffer + nHeaderOffset+pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader); + return XN_STATUS_OK; +} + +XnUInt32 XnHostProtocolGetTimeOut(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nOpcode) +{ + if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeKeepAlive) + return XN_USB_HOST_PROTOCOL_TIMEOUT_KEEP_ALIVE; + else if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeGetVersion) + return XN_USB_HOST_PROTOCOL_TIMEOUT_GETVERSION; + else if (nOpcode == pDevicePrivateData->FWInfo.nOpcodeSetParam) + return XN_USB_HOST_PROTOCOL_TIMEOUT_SETPARAM; + else + return XN_USB_HOST_PROTOCOL_TIMEOUT; +} + +XnUInt32 XnHostProtocolGetSetParamRecvTimeOut(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam) +{ + if (nParam == PARAM_IMAGE_FLICKER_DETECTION) + return pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker; + else if (nParam == PARAM_GENERAL_STREAM0_MODE) + return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode; + else if (nParam == PARAM_GENERAL_STREAM1_MODE) + return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode; + else if (nParam == PARAM_GENERAL_STREAM2_MODE) + return pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode; + else + return 0; +} + +XnStatus XnHostProtocolGetRequestID(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt16* pnRequestId) +{ + XnUInt16 nRequestId; + + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) + { + nRequestId = ((XnHostProtocolHeaderV26*)(pBuffer))->nId; + } + else + { + nRequestId = ((XnHostProtocolHeaderV25*)(pBuffer))->nId; + } + + *pnRequestId = XN_PREPARE_VAR16_IN_BUFFER(nRequestId); + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolReceiveReply(XnDevicePrivateData* pDevicePrivateData, XnUChar* pBuffer, XnUInt16 nBufferSize, XnUInt32 nTimeOut, XnUInt16 nOpcode, XnUInt16 nRequestId, XnUInt32* pnReadBytes, XnUInt16* pnDataSize, XnUChar** ppRelevantBuffer, XnBool bForceBulk, XnUInt32 nRecvTimeout, XnUInt32 nFailTimeout) +{ + XnStatus rc = XN_STATUS_OK; + + XnUInt64 nStartWaitingTime; + xnOSGetTimeStamp(&nStartWaitingTime); + + while (TRUE) // loop until timeout expires + { + do // loop until right reply ID is received + { + // receive reply + if (nRecvTimeout != 0) + { + xnOSSleep(nRecvTimeout); + } + + rc = XnHostProtocolUSBReceive(pDevicePrivateData, pBuffer, pDevicePrivateData->FWInfo.nProtocolMaxPacketSize, *pnReadBytes, nTimeOut, bForceBulk, nFailTimeout); + XN_IS_STATUS_OK(rc); + + // Validate the reply + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_2) + { + rc = ValidateReplyV26(pDevicePrivateData, pBuffer, *pnReadBytes, nOpcode, nRequestId, *pnDataSize, ppRelevantBuffer); + } + else + { + rc = ValidateReplyV25(pDevicePrivateData, pBuffer, *pnReadBytes, nOpcode, nRequestId, *pnDataSize, ppRelevantBuffer); + } + } while (rc == XN_STATUS_DEVICE_PROTOCOL_WRONG_ID); + + XnUInt64 nNow; + xnOSGetTimeStamp(&nNow); + + if (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC) + { + return rc; + } + else if (rc == XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC && (nNow-nStartWaitingTime)>XN_RECEIVE_USB_DATA_TIMEOUT) + { + // Timeout expired + return XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC; + } + else if (rc == XN_STATUS_DEVICE_PROTOCOL_BAD_MAGIC) + { + // Timeout not expired yet + xnOSSleep(10); + } + else + { + // OK + break; + } + } + + return rc; +} + +XnStatus XnHostProtocolExecute(XnDevicePrivateData* pDevicePrivateData, + XnUChar* pBuffer, XnUInt16 nSize, XnUInt16 nOpcode, + XnUChar** ppRelevantBuffer, XnUInt16& nDataSize, XnUInt32 nRecvTimeout = 0) +{ + XnStatus rc; + XnUInt32 nRead; + XnUInt32 nFailTimeout = 0; + + XnBool bForceBulk = FALSE; + + if (nOpcode == OPCODE_INVALID) + { + return (XN_STATUS_DEVICE_PROTOCOL_UNSUPPORTED_OPCODE); + } + + XnUInt32 nTimeOut = XnHostProtocolGetTimeOut(pDevicePrivateData, nOpcode); + + // store request (in case we need to retry it) + XnUChar request[MAX_PACKET_SIZE]; + xnOSMemCopy(request, pBuffer, nSize); + + XnUInt16 nRequestId; + rc = XnHostProtocolGetRequestID(pDevicePrivateData, pBuffer, &nRequestId); + XN_IS_STATUS_OK(rc); + + XnUInt16 nRetriesLeft = XN_HOST_PROTOCOL_NOT_READY_RETRIES; + while (nRetriesLeft-- > 0) // loop until device is ready + { + rc = xnOSLockMutex(pDevicePrivateData->hExecuteMutex, XN_WAIT_INFINITE); + XN_IS_STATUS_OK(rc); + + // Sleep before sending the control + xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend); + + // Send request + rc = XnHostProtocolUSBSend(pDevicePrivateData, request, nSize, nRead, nTimeOut, bForceBulk); + if (rc != XN_STATUS_OK) + { + xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); + return rc; + } + + // Sleep before trying to read the reply + xnOSSleep(pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend); + + // receive reply + rc = XnHostProtocolReceiveReply(pDevicePrivateData, pBuffer, nSize, nTimeOut, nOpcode, nRequestId, &nRead, &nDataSize, ppRelevantBuffer, bForceBulk, nRecvTimeout, nFailTimeout); + + if (rc == XN_STATUS_DEVICE_PROTOCOL_NOT_READY || rc == XN_STATUS_OK) + { + XnStatus unlockRC = xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); + XN_IS_STATUS_OK(unlockRC); + } + else + { + xnOSUnLockMutex(pDevicePrivateData->hExecuteMutex); + return rc; + } + + if (rc == XN_STATUS_OK) + break; + + xnOSSleep(1000); + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Device not ready. %d more retries...", nRetriesLeft); + } + + XN_IS_STATUS_OK(rc); + + if (ppRelevantBuffer == NULL) + return XN_STATUS_OK; + + // Get rest of data + XnInt32 nDataRead = 0; + + XnInt32 nCur = nRead; // Read so far + + nRead -= (pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnHostProtocolReplyHeader)); // Data read so far + + while (nRead < nDataSize*2U) + { + XnUInt32 dummy = 0; + + rc = XnHostProtocolUSBReceive(pDevicePrivateData, pBuffer+nCur, pDevicePrivateData->FWInfo.nProtocolMaxPacketSize, dummy, nTimeOut, bForceBulk, 0); + if (rc != XN_STATUS_OK) + { + return rc; + } + + nCur += dummy; + nRead += dummy; + } + + nDataRead = nRead; + + return XN_STATUS_OK; +} + + +XnStatus XnHostProtocolGetVersion(XnDevicePrivateData* pDevicePrivateData, XnVersions& Version) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + XnUInt16 nDataSize; + XnVersions *pVersion = NULL; + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting hardware versions..."); + + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetVersion); + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetVersion, + (XnUChar**)(&pVersion), nDataSize); + if (rc != XN_STATUS_OK) + { + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_1); + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetVersion); + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetVersion, + (XnUChar**)(&pVersion), nDataSize); + + if (rc != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get version failed: %s", xnGetStatusString(rc)); + + return rc; + } + } + + xnOSMemCopy(&Version, pVersion, sizeof(XnVersions)); + + Version.nBuild = XN_PREPARE_VAR16_IN_BUFFER(Version.nBuild); + Version.nChip = XN_PREPARE_VAR32_IN_BUFFER(Version.nChip); + Version.nFPGA = XN_PREPARE_VAR16_IN_BUFFER(Version.nFPGA); + Version.nSystemVersion = XN_PREPARE_VAR16_IN_BUFFER(Version.nSystemVersion); + + *((XnUInt16*)&Version) = xnOSEndianSwapUINT16(*((XnUInt16*)pVersion)); + + if (Version.nMajor > 5 || (Version.nMajor == 5 && Version.nMinor > 3)) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Sensor version %d.%d is newer than latest known. Trying to use 5.3 protocol...", Version.nMajor, Version.nMinor); + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_3); + } + else if (Version.nMajor == 5 && Version.nMinor == 3) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_3); + else if (Version.nMajor == 5 && Version.nMinor == 2) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_2); + else if (Version.nMajor == 5 && Version.nMinor == 1) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_1); + else if (Version.nMajor == 5 && Version.nMinor == 0) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_5_0); + else if (Version.nMajor >= 4) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_4_0); + else if (Version.nMajor == 3 && Version.nMinor == 0) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_3_0); + else if (Version.nMajor == 1 && Version.nMinor == 2) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_2); + else if (Version.nMajor == 1 && Version.nMinor == 1) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_1_1); + else if (Version.nMajor == 0) + XnHostProtocolInitFWParams(pDevicePrivateData, XN_SENSOR_FW_VER_0_17); + + Version.SDK.nMajor = XN_PS_MAJOR_VERSION; + Version.SDK.nMinor = XN_PS_MINOR_VERSION; + Version.SDK.nMaintenance = XN_PS_MAINTENANCE_VERSION; + Version.SDK.nBuild = XN_PS_BUILD_VERSION; + + if (Version.nFPGA == XN_FPGA_VER_FPDB_26) + { + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_FPDB_10; + } + else if (Version.nFPGA == XN_FPGA_VER_FPDB_25) + { + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_FPDB_10; + } + else if (Version.nFPGA == XN_FPGA_VER_CDB) + { + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_CDB_10; + } + else + { + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_UNKNOWN; + } + + if (Version.nChip == XN_CHIP_VER_PS1000) + { + pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_PS1000; + } + else if (Version.nChip == XN_CHIP_VER_PS1080) + { + pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_PS1080; + } + else + { + pDevicePrivateData->ChipInfo.nChipVer = XN_SENSOR_CHIP_VER_UNKNOWN; + } + + if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_4_0) + { + pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_4_0; + } + else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_3_0) + { + pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_3_0; + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_RD_3; + } + else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_5_0 || pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_5_1) + { + pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_5_0; + pDevicePrivateData->HWInfo.nHWVer = XN_SENSOR_HW_VER_RD_5; + } + else + { + pDevicePrivateData->SensorInfo.nSensorVer = XN_SENSOR_VER_2_0; + } + + Version.FWVer = pDevicePrivateData->FWInfo.nFWVer; + Version.HWVer = pDevicePrivateData->HWInfo.nHWVer; + Version.SensorVer = pDevicePrivateData->SensorInfo.nSensorVer; + Version.ChipVer = pDevicePrivateData->ChipInfo.nChipVer; + + if (Version.nMajor >= 5) + { + XnChar cpBuffer[XN_MAX_OS_NAME_LENGTH]; + sprintf(cpBuffer, "%x", Version.nBuild); + Version.nBuild = atoi(cpBuffer); + } + + if ((Version.nMajor >= 5) && (Version.nMinor >= 3) && (Version.nBuild >= 16)) + { + pDevicePrivateData->FWInfo.nUSBDelayReceive = 1; + pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend = 0; + pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend = 0; + pDevicePrivateData->FWInfo.nUSBDelaySoftReset = 1; + pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 1; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode = 1; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode = 1; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode = 1; + } + else + { + pDevicePrivateData->FWInfo.nUSBDelayReceive = 100; + pDevicePrivateData->FWInfo.nUSBDelayExecutePreSend = 1; + pDevicePrivateData->FWInfo.nUSBDelayExecutePostSend = 10; + pDevicePrivateData->FWInfo.nUSBDelaySoftReset = 800; + pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 3000; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream0Mode = 1; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream1Mode = 300; + pDevicePrivateData->FWInfo.nUSBDelaySetParamStream2Mode = 1; + + if ((Version.nMajor == 5) && (Version.nMinor == 3) && (Version.nBuild == 15)) + { + pDevicePrivateData->FWInfo.nUSBDelaySetParamFlicker = 300; + } + } + + xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Hardware versions: FW=%d.%d.%d (%d) HW=%d Chip=%d Sensor=%d SYS=%d", Version.nMajor, Version.nMinor, Version.nBuild, Version.FWVer, Version.HWVer, Version.ChipVer, Version.SensorVer, Version.nSystemVersion); + + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolKeepAlive(XnDevicePrivateData* pDevicePrivateData) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Requesting KeepAlive..."); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeKeepAlive); + + XnUInt16 nDataSize; + + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeKeepAlive, + NULL, nDataSize); + + if (rc == XN_STATUS_OK) + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Got KeepAlive Reply."); + else + xnLogError(XN_MASK_SENSOR_PROTOCOL, "KeepAlive failed: %s", xnGetStatusString(rc)); + + return rc; +} + + +XnStatus XnHostProtocolGetParam(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16& nValue) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + +// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Getting Parameter [%d]...", nParam); + + *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nParam); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetParam); + + XnUInt16 nDataSize; + XnUInt16* pValue = NULL; + + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetParam, + (XnUChar**)(&pValue), nDataSize); + if (rc != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed getting [%d]: %s", nParam, xnGetStatusString(rc)); + return rc; + } + +// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Param[%d] = %d", nParam, *pValue); + nValue = XN_PREPARE_VAR16_IN_BUFFER(*pValue); + + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolSetParam(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16 nValue) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + +// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Setting Parameter [%d] to %d", nParam, nValue); + + *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nParam); + *(((XnUInt16*)pDataBuf)+1) = XN_PREPARE_VAR16_IN_BUFFER(nValue); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16)*2, pDevicePrivateData->FWInfo.nOpcodeSetParam); + + XnUInt16 nDataSize; + + XnInt32 nTimesLeft = 5; + XnStatus rc = XN_STATUS_ERROR; + while (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS && + rc != XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND && nTimesLeft > 0) + { + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16)*2, pDevicePrivateData->FWInfo.nOpcodeSetParam, + NULL, nDataSize, XnHostProtocolGetSetParamRecvTimeOut(pDevicePrivateData, nParam)); + nTimesLeft--; + + if (rc != XN_STATUS_OK) + { + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Retrying to set the param... rc=%d", rc); + } + } + + if (rc != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed setting [%d] to [%d]: %s", nParam, nValue, xnGetStatusString(rc)); + } + else + { +// xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Done."); + } + + return rc; +} + +void XnHostPrototcolAdjustFixedParamsV26(XnFixedParamsV26* pFixedParamsV26, XnFixedParams* pFixedParams) +{ + // the only difference from V2.6 to V3.0 is the 4 last parameters + xnOSMemCopy(pFixedParams, pFixedParamsV26, sizeof(XnFixedParamsV26)); + pFixedParams->nUseExtPhy = pFixedParamsV26->nUseExtPhy; + pFixedParams->bProjectorProtectionEnabled = FALSE; + pFixedParams->nProjectorDACOutputVoltage = FALSE; + pFixedParams->nTecEmitterDelay = pFixedParamsV26->nTecEmitterDelay; +} + +void XnHostPrototcolAdjustFixedParamsV20(XnFixedParamsV20* pFixedParamsV20, XnFixedParams* pFixedParams) +{ + // the only difference from V2.0 to V2.6 is the addition of nUseExtPhy + XnFixedParamsV26 fixedParamsV26; + xnOSMemCopy(&fixedParamsV26, pFixedParamsV20, sizeof(XnFixedParamsV20)); + + // now adjust from V2.6 to current + XnHostPrototcolAdjustFixedParamsV26(&fixedParamsV26, pFixedParams); +} + +XnStatus XnHostProtocolGetFixedParams(XnDevicePrivateData* pDevicePrivateData, XnFixedParams& FixedParams) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + XnUChar* pRelevantBuffer; + XnUInt16 nFixedParamSize = 0; + + XnChar FixedParamsBuffer[2048] = {0}; + XnChar* pData = FixedParamsBuffer; + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting the fixed params..."); + + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_3_0) + { + nFixedParamSize = sizeof(XnFixedParams); + } + else if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_1) + { + nFixedParamSize = sizeof(XnFixedParamsV26); + } + else // v0.17 + { + nFixedParamSize = sizeof(XnFixedParamsV20); + } + + xnOSMemSet(&FixedParams, 0, sizeof(XnFixedParams)); + + XnInt16 nDataRead = 0; + + XnStatus rc; + while (nDataRead < nFixedParamSize) + { + *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(XnUInt16(nDataRead/sizeof(XnUInt32))); + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetFixedParams); + + XnUInt16 nDataSize; + + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeGetFixedParams, + &pRelevantBuffer, nDataSize); + + if (rc != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get fixed params failed: %s", xnGetStatusString(rc)); + + return rc; + } + + XnUInt32 nReadNow = nDataSize*sizeof(XnUInt16); + if (nReadNow == 0) + { + break; + } + + xnOSMemCopy(pData + nDataRead, pRelevantBuffer, nReadNow); + + nDataRead += nReadNow; + } + + for (XnUInt32 i = 0; i < nFixedParamSize/sizeof(XnUInt32); i ++) + { + XnUInt32 temp = *((XnUInt32*)(&FixedParams)+i); + *((XnUInt32*)(&FixedParams)+i) = XN_PREPARE_VAR32_IN_BUFFER(temp); + } + + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_3_0) + { + xnOSMemCopy(&FixedParams, FixedParamsBuffer, sizeof(XnFixedParams)); + } + else if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_1_1) + { + XnFixedParamsV26 fixedParamsV26; + xnOSMemCopy(&fixedParamsV26, FixedParamsBuffer, nFixedParamSize); + XnHostPrototcolAdjustFixedParamsV26(&fixedParamsV26, &FixedParams); + } + else if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_0_17) + { + XnFixedParamsV20 fixedParamsV20; + xnOSMemCopy(&fixedParamsV20, FixedParamsBuffer, nFixedParamSize); + XnHostPrototcolAdjustFixedParamsV20(&fixedParamsV20, &FixedParams); + } + + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolGetMode(XnDevicePrivateData* pDevicePrivateData, XnUInt16& nMode) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, 0, pDevicePrivateData->FWInfo.nOpcodeGetMode); + + XnUInt16 nDataSize; + XnUInt16* pMode = NULL; + + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize, pDevicePrivateData->FWInfo.nOpcodeGetMode, + (XnUChar**)(&pMode), nDataSize); + if (rc != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Get mode failed: %s", xnGetStatusString(rc)); + + return rc; + } + nMode = XN_PREPARE_VAR16_IN_BUFFER(*pMode); + + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolReset(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nResetType) +{ + XnStatus rc = XN_STATUS_OK; + + if (pDevicePrivateData->FWInfo.nFWVer == XN_SENSOR_FW_VER_0_17) + { + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nResetType); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeReset); + + XnUInt16 nDataSize; + + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeReset, + NULL, nDataSize); + + // Power reset can't fail, and device won't have time to send ACK. + if (nResetType == XN_RESET_TYPE_POWER) + rc = XN_STATUS_OK; + + return rc; + } + else + { + XnUInt16 nActualValue; + switch (nResetType) + { + case XN_RESET_TYPE_POWER: + nActualValue = XN_HOST_PROTOCOL_MODE_REBOOT; + break; + case XN_RESET_TYPE_SOFT: + { + // also kill streams before (in FW < 5.2) + if (pDevicePrivateData->FWInfo.nFWVer < XN_SENSOR_FW_VER_5_2) + { + XnSensorFirmwareParams* pParams = pDevicePrivateData->pSensor->GetFirmware()->GetParams(); + rc = pParams->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); + XN_IS_STATUS_OK(rc); + rc = pParams->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); + XN_IS_STATUS_OK(rc); + rc = pParams->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); + XN_IS_STATUS_OK(rc); + } + } + + nActualValue = XN_HOST_PROTOCOL_MODE_SOFT_RESET; + break; + case XN_RESET_TYPE_SOFT_FIRST: + nActualValue = XN_HOST_PROTOCOL_MODE_SOFT_RESET; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + return XnHostProtocolSetMode(pDevicePrivateData, nActualValue); + } +} + +XnStatus XnHostProtocolSetMode(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nMode) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + *(XnUInt16*)pDataBuf = XN_PREPARE_VAR16_IN_BUFFER(nMode); + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Setting mode to %d...", nMode); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeSetMode); + + XnUInt16 nDataSize; + + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16), pDevicePrivateData->FWInfo.nOpcodeSetMode, + NULL, nDataSize); + + // Patch: always return OK when switching modes (since the firmware is changing there is nobody to ACK the request...) + return XN_STATUS_OK; +} + + +#pragma pack (push, 1) +typedef struct XnAlgorithmParamRequest +{ + XnUInt16 nParamID; + XnUInt16 nFormat; + XnUInt16 nResolution; + XnUInt16 nFPS; + XnUInt16 nOffset; +} XnAlgorithmParamRequest; + +typedef struct XnAlgorithmParamRequestV4 +{ + XnUInt8 nResolution; + XnUInt8 nFPS; + XnUInt8 nFormat; + XnUInt8 nParamID; + XnUInt16 nOffset; +} XnAlgorithmParamRequestV4; +#pragma pack (pop) + +XnStatus XnHostProtocolAlgorithmParams(XnDevicePrivateData* pDevicePrivateData, + XnHostProtocolAlgorithmType eAlgorithmType, + void* pAlgorithmInformation, XnUInt16 nAlgInfoSize, XnResolutions nResolution, XnUInt16 nFPS) +{ + XnChar* pData = (XnChar*)pAlgorithmInformation; + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + XnUChar* pRelevantBuffer; + + XnInt16 nDataRead = 0; + XnUInt16 nRequestSize = 0; + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting algorithm params 0x%x for resolution %d and fps %d....", eAlgorithmType, nResolution, nFPS); + + XnStatus rc; + while (nDataRead < nAlgInfoSize) + { + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1) + { + XnAlgorithmParamRequest* pRequest = (XnAlgorithmParamRequest*)pDataBuf; + pRequest->nParamID = XN_PREPARE_VAR16_IN_BUFFER(eAlgorithmType); + pRequest->nFormat = 0; + pRequest->nResolution = XN_PREPARE_VAR16_IN_BUFFER(nResolution); + pRequest->nFPS = XN_PREPARE_VAR16_IN_BUFFER(nFPS); + pRequest->nOffset = XN_PREPARE_VAR16_IN_BUFFER(nDataRead / sizeof(XnUInt16)); + nRequestSize = sizeof(XnAlgorithmParamRequest); + } + else + { + XnAlgorithmParamRequestV4* pRequest = (XnAlgorithmParamRequestV4*)pDataBuf; + pRequest->nParamID = eAlgorithmType; + pRequest->nFormat = 0; + pRequest->nResolution = nResolution; + pRequest->nFPS = 0; + pRequest->nOffset = XN_PREPARE_VAR16_IN_BUFFER(nDataRead / sizeof(XnUInt16)); + nRequestSize = sizeof(XnAlgorithmParamRequestV4); + } + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, nRequestSize, pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams); + + XnUInt16 nDataSize; + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+nRequestSize, pDevicePrivateData->FWInfo.nOpcodeAlgorithmParams, + &pRelevantBuffer, nDataSize); + + + if (rc != XN_STATUS_OK) + return rc; + + XnUInt32 nReadNow = nDataSize*sizeof(XnUInt16); + if (nReadNow == 0) + { + break; + } + + xnOSMemCopy(pData + nDataRead, pRelevantBuffer, nReadNow); + + nDataRead += nReadNow; + } + + if (nDataRead != nAlgInfoSize) + { + XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_INVALID_RESPONSE_SIZE, XN_MASK_SENSOR_PROTOCOL, "Failed getting algorithm params: expected %u bytes, but got only %u", nAlgInfoSize, nDataRead); + } + + return XN_STATUS_OK; +} + + +XnStatus XnHostProtocolSetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate nSampleRate) +{ + EA2d_SampleRate nSample; + + switch (nSampleRate) + { + case XN_SAMPLE_RATE_8K: + nSample = A2D_SAMPLE_RATE_8KHZ; + break; + case XN_SAMPLE_RATE_11K: + nSample = A2D_SAMPLE_RATE_11KHZ; + break; + case XN_SAMPLE_RATE_12K: + nSample = A2D_SAMPLE_RATE_12KHZ; + break; + case XN_SAMPLE_RATE_16K: + nSample = A2D_SAMPLE_RATE_16KHZ; + break; + case XN_SAMPLE_RATE_22K: + nSample = A2D_SAMPLE_RATE_22KHZ; + break; + case XN_SAMPLE_RATE_24K: + nSample = A2D_SAMPLE_RATE_24KHZ; + break; + case XN_SAMPLE_RATE_32K: + nSample = A2D_SAMPLE_RATE_32KHZ; + break; + case XN_SAMPLE_RATE_44K: + nSample = A2D_SAMPLE_RATE_44KHZ; + break; + case XN_SAMPLE_RATE_48K: + nSample = A2D_SAMPLE_RATE_48KHZ; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + return XnHostProtocolSetParam(pDevicePrivateData, PARAM_AUDIO_SAMPLE_RATE, nSample); +} + +XnStatus XnHostProtocolGetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate* pSampleRate) +{ + XnUInt16 nValue; + XnHostProtocolGetParam(pDevicePrivateData, PARAM_AUDIO_SAMPLE_RATE, nValue); + XnSampleRate nSample; + + switch (nValue) + { + case A2D_SAMPLE_RATE_8KHZ: + nSample = XN_SAMPLE_RATE_8K; + break; + case A2D_SAMPLE_RATE_11KHZ: + nSample = XN_SAMPLE_RATE_11K; + break; + case A2D_SAMPLE_RATE_12KHZ: + nSample = XN_SAMPLE_RATE_12K; + break; + case A2D_SAMPLE_RATE_16KHZ: + nSample = XN_SAMPLE_RATE_16K; + break; + case A2D_SAMPLE_RATE_22KHZ: + nSample = XN_SAMPLE_RATE_22K; + break; + case A2D_SAMPLE_RATE_24KHZ: + nSample = XN_SAMPLE_RATE_24K; + break; + case A2D_SAMPLE_RATE_32KHZ: + nSample = XN_SAMPLE_RATE_32K; + break; + case A2D_SAMPLE_RATE_44KHZ: + nSample = XN_SAMPLE_RATE_44K; + break; + case A2D_SAMPLE_RATE_48KHZ: + nSample = XN_SAMPLE_RATE_48K; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + *pSampleRate = nSample; + + return (XN_STATUS_OK); +} + + +XnStatus XnHostProtocolSetMultipleParams(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nNumOfParams, XnInnerParamData* anParams) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + XnUInt16* pCurData = (XnUInt16*)pDataBuf; + for (XnUInt16 nIndex = 0; nIndex < nNumOfParams; ++nIndex) + { + *pCurData++ = XN_PREPARE_VAR16_IN_BUFFER(anParams[nIndex].nParam); + *pCurData++ = XN_PREPARE_VAR16_IN_BUFFER(anParams[nIndex].nValue); + } + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnUInt16)*nNumOfParams*2, pDevicePrivateData->FWInfo.nOpcodeSetParam); + + XnUInt16 nDataSize; + + XnInt32 nTimesLeft = 5; + XnStatus rc = XN_STATUS_ERROR; + while (rc != XN_STATUS_OK && rc != XN_STATUS_DEVICE_PROTOCOL_BAD_PARAMS && + rc != XN_STATUS_DEVICE_PROTOCOL_INVALID_COMMAND && nTimesLeft > 0) + { + rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize+sizeof(XnUInt16)*nNumOfParams*2, pDevicePrivateData->FWInfo.nOpcodeSetParam, + NULL, nDataSize); + nTimesLeft--; + } + + if (rc != XN_STATUS_OK) + xnLogError(XN_MASK_SENSOR_PROTOCOL, "Failed: %s", xnGetStatusString(rc)); + + return rc; +} + + +XnStatus XnHostProtocolSetIRCropping(XnDevicePrivateData* pDevicePrivateData, XnCropping* pCropping) +{ + XnStatus rc = XN_STATUS_OK; + + if (pCropping->bEnabled) + { + XnInnerParamData anParams[4]; + XnUInt16 nIndex = 0; + + anParams[nIndex].nParam = PARAM_IR_CROP_SIZE_X; + anParams[nIndex].nValue = pCropping->nXSize; + nIndex++; + anParams[nIndex].nParam = PARAM_IR_CROP_SIZE_Y; + anParams[nIndex].nValue = pCropping->nYSize; + nIndex++; + anParams[nIndex].nParam = PARAM_IR_CROP_OFFSET_X; + anParams[nIndex].nValue = pCropping->nXOffset; + nIndex++; + anParams[nIndex].nParam = PARAM_IR_CROP_OFFSET_Y; + anParams[nIndex].nValue = pCropping->nYOffset; + + rc = XnHostProtocolSetMultipleParams(pDevicePrivateData, 4, anParams); + if (rc != XN_STATUS_OK) + return rc; + } + + // commit + rc = XnHostProtocolSetParam(pDevicePrivateData, PARAM_IR_CROP_ENABLE, pCropping->bEnabled); + + return rc; +} + + +XnStatus XnDeviceSensorGetDepthAGCParams(XnUInt16 nBin, XnUInt16* pnMinParam, XnUInt16* pnMaxParam) +{ + switch (nBin) + { + case 0: + *pnMinParam = PARAM_DEPTH_AGC_BIN0_LOW; + *pnMaxParam = PARAM_DEPTH_AGC_BIN0_HIGH; + break; + case 1: + *pnMinParam = PARAM_DEPTH_AGC_BIN1_LOW; + *pnMaxParam = PARAM_DEPTH_AGC_BIN1_HIGH; + break; + case 2: + *pnMinParam = PARAM_DEPTH_AGC_BIN2_LOW; + *pnMaxParam = PARAM_DEPTH_AGC_BIN2_HIGH; + break; + case 3: + *pnMinParam = PARAM_DEPTH_AGC_BIN3_LOW; + *pnMaxParam = PARAM_DEPTH_AGC_BIN3_HIGH; + break; + default: + return XN_STATUS_DEVICE_BAD_PARAM; + } + + return XN_STATUS_OK; +} + +XnStatus XnHostProtocolSetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16 nMinShift, XnUInt16 nMaxShift) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt16 nMinParam; + XnUInt16 nMaxParam; + + nRetVal = XnDeviceSensorGetDepthAGCParams(nBin, &nMinParam, &nMaxParam); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnHostProtocolSetParam(pDevicePrivateData, nMinParam, nMinShift); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnHostProtocolSetParam(pDevicePrivateData, nMaxParam, nMaxShift); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnHostProtocolGetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16* pnMinShift, XnUInt16* pnMaxShift) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt16 nMinParam; + XnUInt16 nMaxParam; + + nRetVal = XnDeviceSensorGetDepthAGCParams(nBin, &nMinParam, &nMaxParam); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnHostProtocolGetParam(pDevicePrivateData, nMinParam, *pnMinShift); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnHostProtocolGetParam(pDevicePrivateData, nMaxParam, *pnMaxShift); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +#pragma pack (push, 1) + +typedef struct XnVSyncRequest +{ + XnUInt16 nUnits; + XnUInt16 nCmosID; + XnUInt16 nNumberOfFrames; +} XnVSyncRequest; + +#pragma pack (pop) + +XnStatus XnHostProtocolSetCmosBlanking(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nUnits, XnCMOSType nCMOSID, XnUInt16 nNumberOfFrames) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + XnUInt32 nRequestSize; + + if (pDevicePrivateData->FWInfo.nFWVer >= XN_SENSOR_FW_VER_5_1) + { + XnVSyncRequest* pRequest = (XnVSyncRequest*)pDataBuf; + pRequest->nUnits = XN_PREPARE_VAR16_IN_BUFFER(nUnits); + pRequest->nCmosID = XN_PREPARE_VAR16_IN_BUFFER(nCMOSID); + pRequest->nNumberOfFrames = XN_PREPARE_VAR16_IN_BUFFER(nNumberOfFrames); + nRequestSize = sizeof(XnVSyncRequest); + } + else + { + XN_LOG_WARNING_RETURN(XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED, XN_MASK_SENSOR_PROTOCOL, "Set Blanking is not supported by this firmware!"); + } + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Chaning CMOS %d Blanking to %hd (NumberOfFrames=%hu)...", nCMOSID, nUnits, nNumberOfFrames); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, nRequestSize, pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking); + + XnUInt16 nDataSize; + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize + nRequestSize, pDevicePrivateData->FWInfo.nOpcodeSetCmosBlanking, + NULL, nDataSize); + + if (rc != XN_STATUS_OK) + { + XN_LOG_WARNING_RETURN(rc, XN_MASK_SENSOR_PROTOCOL, "Failed changing CMOS %d Blanking to %hd (NumberOfFrames=%hu): %s", nCMOSID, nUnits, nNumberOfFrames, xnGetStatusString(rc)); + } + + return (XN_STATUS_OK); +} + +#pragma pack (push, 1) + +typedef struct XnGetCmosBlankingRequest +{ + XnUInt16 nCmosID; +} XnGetCmosBlankingRequest; + +typedef struct XnGetCmosBlankingReply +{ + XnUInt32 nUnits; +} XnGetCmosBlankingReply; + +#pragma pack (pop) + +XnStatus XnHostProtocolGetCmosBlanking(XnDevicePrivateData* pDevicePrivateData, XnCMOSType nCMOSID, XnUInt16* pnLines) +{ + XnUChar buffer[MAX_PACKET_SIZE] = {0}; + XnUChar* pDataBuf = buffer + pDevicePrivateData->FWInfo.nProtocolHeaderSize; + + XnGetCmosBlankingRequest* pRequest = (XnGetCmosBlankingRequest*)pDataBuf; + pRequest->nCmosID = nCMOSID; + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "Getting Cmos %d VBlanking...", nCMOSID); + + XnHostProtocolInitHeader(pDevicePrivateData, buffer, pDataBuf, sizeof(XnGetCmosBlankingRequest), pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking); + + XnGetCmosBlankingReply* pReply; + XnUInt16 nDataSize; + XnStatus rc = XnHostProtocolExecute(pDevicePrivateData, + buffer, pDevicePrivateData->FWInfo.nProtocolHeaderSize + sizeof(XnGetCmosBlankingRequest), pDevicePrivateData->FWInfo.nOpcodeGetCmosBlanking, + (XnUChar**)&pReply, nDataSize); + + if (rc != XN_STATUS_OK) + { + XN_LOG_WARNING_RETURN(rc, XN_MASK_SENSOR_PROTOCOL, "Failed getting Cmos %d Blanking: %s", nCMOSID, xnGetStatusString(rc)); + } + + xnLogInfo(XN_MASK_SENSOR_PROTOCOL, "Cmos %d VBlanking: %u", nCMOSID, pReply->nUnits); + + *pnLines = pReply->nUnits; + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/XnHostProtocol.h b/Source/XnDeviceSensorV2/XnHostProtocol.h index fcc67fd..7c24182 100644 --- a/Source/XnDeviceSensorV2/XnHostProtocol.h +++ b/Source/XnDeviceSensorV2/XnHostProtocol.h @@ -1,222 +1,222 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef HOST_PROTOCOL_H -#define HOST_PROTOCOL_H - -#include -#include "XnParams.h" -#include "XnDeviceSensor.h" - - -#define XN_HOST_MAGIC_25 0x5053 //PS -#define XN_FW_MAGIC_25 0x5350 //SP -#define XN_HOST_MAGIC_26 0x4d47 //MG -#define XN_FW_MAGIC_26 0x4252 //BR - -#define XN_FPGA_VER_FPDB_26 0x21 -#define XN_FPGA_VER_FPDB_25 0x0 -#define XN_FPGA_VER_CDB 0x1 - -#define XN_CHIP_VER_PS1000 0x00101010 -#define XN_CHIP_VER_PS1080 0x00202020 - -enum EPsProtocolOpCodes -{ - OPCODE_GET_VERSION = 0, - OPCODE_KEEP_ALIVE = 1, - OPCODE_GET_PARAM = 2, - OPCODE_SET_PARAM = 3, - OPCODE_GET_FIXED_PARAMS = 4, - OPCODE_GET_MODE = 5, - OPCODE_SET_MODE = 6, - OPCODE_ALGORITM_PARAMS = 22, - OPCODE_SET_CMOS_BLANKING = 34, - OPCODE_GET_CMOS_BLANKING = 35, -}; - -enum EPsProtocolOpCodes_V400 -{ - OPCODE_V400_GET_VERSION = 0, - OPCODE_V400_KEEP_ALIVE = 1, - OPCODE_V400_GET_PARAM = 2, - OPCODE_V400_SET_PARAM = 3, - OPCODE_V400_GET_FIXED_PARAMS = 4, - OPCODE_V400_GET_MODE = 5, - OPCODE_V400_SET_MODE = 6, - OPCODE_V400_ALGORITM_PARAMS = 22, -}; - -enum EPsProtocolOpCodes_V300 -{ - OPCODE_V300_GET_VERSION = 0, - OPCODE_V300_KEEP_ALIVE = 1, - OPCODE_V300_GET_PARAM = 2, - OPCODE_V300_SET_PARAM = 3, - OPCODE_V300_GET_FIXED_PARAMS = 4, - OPCODE_V300_GET_MODE = 5, - OPCODE_V300_SET_MODE = 6, - OPCODE_V300_ALGORITM_PARAMS = 22, -}; - -enum XnHostProtocolOpcodes_V110 -{ - OPCODE_V110_GET_VERSION = 0, - OPCODE_V110_KEEP_ALIVE = 1, - OPCODE_V110_GET_PARAM = 2, - OPCODE_V110_SET_PARAM = 3, - OPCODE_V110_GET_FIXED_PARAMS = 4, - OPCODE_V110_GET_MODE = 5, - OPCODE_V110_SET_MODE = 6, - OPCODE_V110_ALGORITHM_PARAMS = 22, -}; - -enum EPsProtocolOpCodes_V017 -{ - OPCODE_V017_GET_VERSION = 0, - OPCODE_V017_KEEP_ALIVE = 1, - OPCODE_V017_GET_PARAM = 2, - OPCODE_V017_SET_PARAM = 3, - OPCODE_V017_GET_FIXED_PARAMS = 4, - OPCODE_V017_RESET = 5, - OPCODE_V017_ALGORITM_PARAMS = 21, -}; - -#define OPCODE_INVALID 0xffff - -typedef enum -{ - XN_HOST_PROTOCOL_ALGORITHM_DEPTH_INFO = 0x00, - XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION = 0x40, - XN_HOST_PROTOCOL_ALGORITHM_PADDING = 0x41, - XN_HOST_PROTOCOL_ALGORITHM_BLANKING = 0x06, - XN_HOST_PROTOCOL_ALGORITHM_FREQUENCY = 0x80 -} XnHostProtocolAlgorithmType; - -typedef enum -{ - XN_HOST_PROTOCOL_MODE_WEBCAM = 0, - XN_HOST_PROTOCOL_MODE_PS, - XN_HOST_PROTOCOL_MODE_MAINTENANCE, - XN_HOST_PROTOCOL_MODE_SOFT_RESET, - XN_HOST_PROTOCOL_MODE_REBOOT, - XN_HOST_PROTOCOL_MODE_SUSPEND, - XN_HOST_PROTOCOL_MODE_RESUME, - XN_HOST_PROTOCOL_MODE_INIT, - XN_HOST_PROTOCOL_MODE_SYSTEM_RESTORE, - XN_HOST_PROTOCOL_MODE_WAIT_FOR_ENUM, - XN_HOST_PROTOCOL_MODE_SAFE_MODE -} XnHostProtocolModeType; - -enum XnHostProtocolNacks -{ - ACK = 0, - NACK_UNKNOWN_ERROR = 1, - NACK_INVALID_COMMAND = 2, - NACK_BAD_PACKET_CRC = 3, - NACK_BAD_PACKET_SIZE = 4, - NACK_BAD_PARAMS = 5, - NACK_BAD_COMMAND_SIZE = 12, - NACK_NOT_READY = 13, - NACK_OVERFLOW = 14 -}; - -typedef enum -{ - A2D_SAMPLE_RATE_48KHZ, - A2D_SAMPLE_RATE_44KHZ, - A2D_SAMPLE_RATE_32KHZ, - A2D_SAMPLE_RATE_24KHZ, - A2D_SAMPLE_RATE_22KHZ, - A2D_SAMPLE_RATE_16KHZ, - A2D_SAMPLE_RATE_12KHZ, - A2D_SAMPLE_RATE_11KHZ, - A2D_SAMPLE_RATE_8KHZ, - A2D_NUM_OF_SAMPLE_RATES -} EA2d_SampleRate; - -#pragma pack(push,1) -typedef struct -{ - XnUInt16 nMagic; - XnUInt16 nSize; - XnUInt16 nOpcode; - XnUInt16 nId; - XnUInt16 nCRC16; -} XnHostProtocolHeaderV25; - -typedef struct -{ - XnUInt16 nMagic; - XnUInt16 nSize; - XnUInt16 nOpcode; - XnUInt16 nId; -} XnHostProtocolHeaderV26; - -typedef struct -{ - XnUInt16 nErrorCode; -} XnHostProtocolReplyHeader; - - -#pragma pack(pop) - -////////////////////////////////////// Exported h file should be only from here down -// Exported params - -// All implemented protocol commands -// Init -XnStatus XnHostProtocolKeepAlive (XnDevicePrivateData* pDevicePrivateData); -XnStatus XnHostProtocolGetVersion (XnDevicePrivateData* pDevicePrivateData, XnVersions& Version); -XnStatus XnHostProtocolAlgorithmParams (XnDevicePrivateData* pDevicePrivateData, - XnHostProtocolAlgorithmType eAlgorithmType, - void* pAlgorithmInformation, XnUInt16 nAlgInfoSize, XnResolutions nResolution, XnUInt16 nFPS); -XnStatus XnHostProtocolSetImageResolution(XnDevicePrivateData* pDevicePrivateData, XnUInt32 nResolutionParamName, XnResolutions nRes); -XnStatus XnHostProtocolSetDepthResolution(XnDevicePrivateData* pDevicePrivateData, XnResolutions nRes); -XnStatus XnHostProtocolGetFixedParams(XnDevicePrivateData* pDevicePrivateData, XnFixedParams& FixedParams); - -XnStatus XnHostProtocolSetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate nSampleRate); -XnStatus XnHostProtocolGetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate* pSampleRate); - -XnStatus XnHostProtocolSetIRCropping (XnDevicePrivateData* pDevicePrivateData, XnCropping* pCropping); -XnStatus XnHostProtocolSetMode (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nMode); -XnStatus XnHostProtocolGetMode (XnDevicePrivateData* pDevicePrivateData, XnUInt16& nMode); - -XnStatus XnHostProtocolSetParam (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16 nValue); -XnStatus XnHostProtocolSetMultipleParams(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nNumOfParams, XnInnerParamData* anParams); -XnStatus XnHostProtocolReset(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nResetType); - -XnStatus XnHostProtocolGetParam (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16& nValue); - -XnStatus XnHostProtocolSetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16 nMinShift, XnUInt16 nMaxShift); -XnStatus XnHostProtocolGetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16* pnMinShift, XnUInt16* pnMaxShift); - -XnStatus XnHostProtocolSetCmosBlanking (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nLines, XnCMOSType nCMOSID, XnUInt16 nNumberOfFrames); -XnStatus XnHostProtocolGetCmosBlanking (XnDevicePrivateData* pDevicePrivateData, XnCMOSType nCMOSID, XnUInt16* pnLines); - - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef HOST_PROTOCOL_H +#define HOST_PROTOCOL_H + +#include +#include "XnParams.h" +#include "XnDeviceSensor.h" + + +#define XN_HOST_MAGIC_25 0x5053 //PS +#define XN_FW_MAGIC_25 0x5350 //SP +#define XN_HOST_MAGIC_26 0x4d47 //MG +#define XN_FW_MAGIC_26 0x4252 //BR + +#define XN_FPGA_VER_FPDB_26 0x21 +#define XN_FPGA_VER_FPDB_25 0x0 +#define XN_FPGA_VER_CDB 0x1 + +#define XN_CHIP_VER_PS1000 0x00101010 +#define XN_CHIP_VER_PS1080 0x00202020 + +enum EPsProtocolOpCodes +{ + OPCODE_GET_VERSION = 0, + OPCODE_KEEP_ALIVE = 1, + OPCODE_GET_PARAM = 2, + OPCODE_SET_PARAM = 3, + OPCODE_GET_FIXED_PARAMS = 4, + OPCODE_GET_MODE = 5, + OPCODE_SET_MODE = 6, + OPCODE_ALGORITM_PARAMS = 22, + OPCODE_SET_CMOS_BLANKING = 34, + OPCODE_GET_CMOS_BLANKING = 35, +}; + +enum EPsProtocolOpCodes_V400 +{ + OPCODE_V400_GET_VERSION = 0, + OPCODE_V400_KEEP_ALIVE = 1, + OPCODE_V400_GET_PARAM = 2, + OPCODE_V400_SET_PARAM = 3, + OPCODE_V400_GET_FIXED_PARAMS = 4, + OPCODE_V400_GET_MODE = 5, + OPCODE_V400_SET_MODE = 6, + OPCODE_V400_ALGORITM_PARAMS = 22, +}; + +enum EPsProtocolOpCodes_V300 +{ + OPCODE_V300_GET_VERSION = 0, + OPCODE_V300_KEEP_ALIVE = 1, + OPCODE_V300_GET_PARAM = 2, + OPCODE_V300_SET_PARAM = 3, + OPCODE_V300_GET_FIXED_PARAMS = 4, + OPCODE_V300_GET_MODE = 5, + OPCODE_V300_SET_MODE = 6, + OPCODE_V300_ALGORITM_PARAMS = 22, +}; + +enum XnHostProtocolOpcodes_V110 +{ + OPCODE_V110_GET_VERSION = 0, + OPCODE_V110_KEEP_ALIVE = 1, + OPCODE_V110_GET_PARAM = 2, + OPCODE_V110_SET_PARAM = 3, + OPCODE_V110_GET_FIXED_PARAMS = 4, + OPCODE_V110_GET_MODE = 5, + OPCODE_V110_SET_MODE = 6, + OPCODE_V110_ALGORITHM_PARAMS = 22, +}; + +enum EPsProtocolOpCodes_V017 +{ + OPCODE_V017_GET_VERSION = 0, + OPCODE_V017_KEEP_ALIVE = 1, + OPCODE_V017_GET_PARAM = 2, + OPCODE_V017_SET_PARAM = 3, + OPCODE_V017_GET_FIXED_PARAMS = 4, + OPCODE_V017_RESET = 5, + OPCODE_V017_ALGORITM_PARAMS = 21, +}; + +#define OPCODE_INVALID 0xffff + +typedef enum +{ + XN_HOST_PROTOCOL_ALGORITHM_DEPTH_INFO = 0x00, + XN_HOST_PROTOCOL_ALGORITHM_REGISTRATION = 0x40, + XN_HOST_PROTOCOL_ALGORITHM_PADDING = 0x41, + XN_HOST_PROTOCOL_ALGORITHM_BLANKING = 0x06, + XN_HOST_PROTOCOL_ALGORITHM_FREQUENCY = 0x80 +} XnHostProtocolAlgorithmType; + +typedef enum +{ + XN_HOST_PROTOCOL_MODE_WEBCAM = 0, + XN_HOST_PROTOCOL_MODE_PS, + XN_HOST_PROTOCOL_MODE_MAINTENANCE, + XN_HOST_PROTOCOL_MODE_SOFT_RESET, + XN_HOST_PROTOCOL_MODE_REBOOT, + XN_HOST_PROTOCOL_MODE_SUSPEND, + XN_HOST_PROTOCOL_MODE_RESUME, + XN_HOST_PROTOCOL_MODE_INIT, + XN_HOST_PROTOCOL_MODE_SYSTEM_RESTORE, + XN_HOST_PROTOCOL_MODE_WAIT_FOR_ENUM, + XN_HOST_PROTOCOL_MODE_SAFE_MODE +} XnHostProtocolModeType; + +enum XnHostProtocolNacks +{ + ACK = 0, + NACK_UNKNOWN_ERROR = 1, + NACK_INVALID_COMMAND = 2, + NACK_BAD_PACKET_CRC = 3, + NACK_BAD_PACKET_SIZE = 4, + NACK_BAD_PARAMS = 5, + NACK_BAD_COMMAND_SIZE = 12, + NACK_NOT_READY = 13, + NACK_OVERFLOW = 14 +}; + +typedef enum +{ + A2D_SAMPLE_RATE_48KHZ, + A2D_SAMPLE_RATE_44KHZ, + A2D_SAMPLE_RATE_32KHZ, + A2D_SAMPLE_RATE_24KHZ, + A2D_SAMPLE_RATE_22KHZ, + A2D_SAMPLE_RATE_16KHZ, + A2D_SAMPLE_RATE_12KHZ, + A2D_SAMPLE_RATE_11KHZ, + A2D_SAMPLE_RATE_8KHZ, + A2D_NUM_OF_SAMPLE_RATES +} EA2d_SampleRate; + +#pragma pack(push,1) +typedef struct +{ + XnUInt16 nMagic; + XnUInt16 nSize; + XnUInt16 nOpcode; + XnUInt16 nId; + XnUInt16 nCRC16; +} XnHostProtocolHeaderV25; + +typedef struct +{ + XnUInt16 nMagic; + XnUInt16 nSize; + XnUInt16 nOpcode; + XnUInt16 nId; +} XnHostProtocolHeaderV26; + +typedef struct +{ + XnUInt16 nErrorCode; +} XnHostProtocolReplyHeader; + + +#pragma pack(pop) + +////////////////////////////////////// Exported h file should be only from here down +// Exported params + +// All implemented protocol commands +// Init +XnStatus XnHostProtocolKeepAlive (XnDevicePrivateData* pDevicePrivateData); +XnStatus XnHostProtocolGetVersion (XnDevicePrivateData* pDevicePrivateData, XnVersions& Version); +XnStatus XnHostProtocolAlgorithmParams (XnDevicePrivateData* pDevicePrivateData, + XnHostProtocolAlgorithmType eAlgorithmType, + void* pAlgorithmInformation, XnUInt16 nAlgInfoSize, XnResolutions nResolution, XnUInt16 nFPS); +XnStatus XnHostProtocolSetImageResolution(XnDevicePrivateData* pDevicePrivateData, XnUInt32 nResolutionParamName, XnResolutions nRes); +XnStatus XnHostProtocolSetDepthResolution(XnDevicePrivateData* pDevicePrivateData, XnResolutions nRes); +XnStatus XnHostProtocolGetFixedParams(XnDevicePrivateData* pDevicePrivateData, XnFixedParams& FixedParams); + +XnStatus XnHostProtocolSetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate nSampleRate); +XnStatus XnHostProtocolGetAudioSampleRate(XnDevicePrivateData* pDevicePrivateData, XnSampleRate* pSampleRate); + +XnStatus XnHostProtocolSetIRCropping (XnDevicePrivateData* pDevicePrivateData, XnCropping* pCropping); +XnStatus XnHostProtocolSetMode (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nMode); +XnStatus XnHostProtocolGetMode (XnDevicePrivateData* pDevicePrivateData, XnUInt16& nMode); + +XnStatus XnHostProtocolSetParam (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16 nValue); +XnStatus XnHostProtocolSetMultipleParams(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nNumOfParams, XnInnerParamData* anParams); +XnStatus XnHostProtocolReset(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nResetType); + +XnStatus XnHostProtocolGetParam (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nParam, XnUInt16& nValue); + +XnStatus XnHostProtocolSetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16 nMinShift, XnUInt16 nMaxShift); +XnStatus XnHostProtocolGetDepthAGCBin(XnDevicePrivateData* pDevicePrivateData, XnUInt16 nBin, XnUInt16* pnMinShift, XnUInt16* pnMaxShift); + +XnStatus XnHostProtocolSetCmosBlanking (XnDevicePrivateData* pDevicePrivateData, XnUInt16 nLines, XnCMOSType nCMOSID, XnUInt16 nNumberOfFrames); +XnStatus XnHostProtocolGetCmosBlanking (XnDevicePrivateData* pDevicePrivateData, XnCMOSType nCMOSID, XnUInt16* pnLines); + + +#endif diff --git a/Source/XnDeviceSensorV2/XnIRProcessor.cpp b/Source/XnDeviceSensorV2/XnIRProcessor.cpp index 6170b9a..8ff310d 100644 --- a/Source/XnDeviceSensorV2/XnIRProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnIRProcessor.cpp @@ -1,273 +1,273 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnIRProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- - -/* The size of an input element for unpacking. */ -#define XN_INPUT_ELEMENT_SIZE 5 -/* The size of an output element for unpacking. */ -#define XN_OUTPUT_ELEMENT_SIZE 8 - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnIRProcessor::XnIRProcessor(XnSensorIRStream* pStream, XnSensorStreamHelper* pHelper) : - XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END) -{ -} - -XnIRProcessor::~XnIRProcessor() -{ -} - -XnStatus XnIRProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnFrameStreamProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_INPUT_ELEMENT_SIZE); - - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE16: - break; - case XN_OUTPUT_FORMAT_RGB24: - XN_VALIDATE_BUFFER_ALLOCATE(m_UnpackedBuffer, GetExpectedOutputSize()); - break; - } - - return (XN_STATUS_OK); -} - -XnStatus XnIRProcessor::Unpack10to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt16* pnOutput, XnUInt32* pnActualRead, XnUInt32* pnOutputSize) -{ - XnInt32 cInput = 0; - const XnUInt8* pOrigInput = pcInput; - - XnUInt32 nElements = nInputSize / XN_INPUT_ELEMENT_SIZE; // floored - XnUInt32 nNeededOutput = nElements * XN_OUTPUT_ELEMENT_SIZE; - - *pnActualRead = 0; - - if (*pnOutputSize < nNeededOutput) - { - *pnOutputSize = 0; - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - // Convert the 10bit packed data into 16bit shorts - - for (XnUInt32 nElem = 0; nElem < nElements; ++nElem) - { - //1a - cInput = *pcInput; - *pnOutput = (cInput & 0xFF) << 2; - - //1b - pcInput++; - cInput = *pcInput; - *pnOutput = *pnOutput | ((cInput & 0xC0) >> 6); - pnOutput++; - - //2a - *pnOutput = (cInput & 0x3F) << 4; - - //2b - pcInput++; - cInput = *pcInput; - *pnOutput = *pnOutput | ((cInput & 0xF0) >> 4); - pnOutput++; - - //3a - *pnOutput = (cInput & 0x0F) << 6; - - //3b - pcInput++; - cInput = *pcInput; - *pnOutput = *pnOutput | ((cInput & 0xFC) >> 2); - pnOutput++; - - //4a - *pnOutput = (cInput & 0x3) << 8; - - //4b - pcInput++; - cInput = *pcInput; - *pnOutput = *pnOutput | (cInput & 0xFF); - pnOutput++; - - pcInput++; - } - - *pnActualRead = pcInput - pOrigInput; - *pnOutputSize = nNeededOutput; - return XN_STATUS_OK; -} - -void XnIRProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnIRProcessor::ProcessFramePacketChunk") - - // if output format is Gray16, we can write directly to output buffer. otherwise, we need - // to write to a temp buffer. - XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE16) ? GetWriteBuffer() : &m_UnpackedBuffer; - - if (m_ContinuousBuffer.GetSize() != 0) - { - // fill in to a whole element - XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); - m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); - pData += nReadBytes; - nDataSize -= nReadBytes; - - if (m_ContinuousBuffer.GetSize() == XN_INPUT_ELEMENT_SIZE) - { - // process it - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - if (XN_STATUS_OK != Unpack10to16(m_ContinuousBuffer.GetData(), XN_INPUT_ELEMENT_SIZE, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), &nActualRead, &nOutputSize)) - WriteBufferOverflowed(); - else - pWriteBuffer->UnsafeUpdateSize(nOutputSize); - - m_ContinuousBuffer.Reset(); - } - } - - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - if (XN_STATUS_OK != Unpack10to16(pData, nDataSize, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), &nActualRead, &nOutputSize)) - { - WriteBufferOverflowed(); - } - else - { - pWriteBuffer->UnsafeUpdateSize(nOutputSize); - - pData += nActualRead; - nDataSize -= nActualRead; - - // if we have any bytes left, store them for next packet - if (nDataSize > 0) - { - // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE - // are left. - m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); - } - } - - XN_PROFILING_END_SECTION -} - -void IRto888(XnUInt16* pInput, XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - XnUInt16* pInputEnd = pInput + nInputSize; - XnUInt8* pOutputOrig = pOutput; - XnUInt8* pOutputEnd = pOutput + *pnOutputSize; - - while (pInput != pInputEnd && pOutput < pOutputEnd) - { - *pOutput = (*pInput)>>2; - *(pOutput+1) = *pOutput; - *(pOutput+2) = *pOutput; - - pOutput+=3; - pInput++; - } - - *pnOutputSize = pOutput - pOutputOrig; -} - -XnUInt32 XnIRProcessor::CalculateExpectedSize() -{ - XnUInt32 nXRes = GetStream()->GetXRes(); - XnUInt32 nYRes = GetStream()->GetYRes(); - - // when cropping is turned on, actual depth size is smaller - if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) - { - nXRes = (XnUInt32)GetStream()->m_FirmwareCropSizeX.GetValue(); - nYRes = (XnUInt32)GetStream()->m_FirmwareCropSizeY.GetValue(); - } - else if (GetStream()->GetResolution() != XN_RESOLUTION_SXGA) - { - // there are additional 8 rows - nYRes += 8; - } - - return nXRes * nYRes * GetStream()->GetBytesPerPixel(); -} - -void XnIRProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XN_PROFILING_START_SECTION("XnIRProcessor::OnEndOfFrame") - - // if there are bytes left in continuous buffer, then we have a corrupt frame - if (m_ContinuousBuffer.GetSize() != 0) - { - xnLogWarning(XN_MASK_SENSOR_READ, "IR buffer is corrupt. There are left over bytes (invalid size)"); - FrameIsCorrupted(); - } - - // if data was written to temp buffer, convert it now - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE16: - break; - case XN_OUTPUT_FORMAT_RGB24: - { - XnUInt32 nOutputSize = GetWriteBuffer()->GetFreeSpaceInBuffer(); - IRto888((XnUInt16*)m_UnpackedBuffer.GetData(), m_UnpackedBuffer.GetSize() / sizeof(XnUInt16), GetWriteBuffer()->GetUnsafeWritePointer(), &nOutputSize); - GetWriteBuffer()->UnsafeUpdateSize(nOutputSize); - m_UnpackedBuffer.Reset(); - } - break; - } - - XnUInt32 nExpectedBufferSize = CalculateExpectedSize(); - if (GetWriteBuffer()->GetSize() != nExpectedBufferSize) - { - xnLogWarning(XN_MASK_SENSOR_READ, "IR buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedBufferSize); - FrameIsCorrupted(); - } - - XnFrameStreamProcessor::OnEndOfFrame(pHeader); - m_ContinuousBuffer.Reset(); - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnIRProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +/* The size of an input element for unpacking. */ +#define XN_INPUT_ELEMENT_SIZE 5 +/* The size of an output element for unpacking. */ +#define XN_OUTPUT_ELEMENT_SIZE 8 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnIRProcessor::XnIRProcessor(XnSensorIRStream* pStream, XnSensorStreamHelper* pHelper) : + XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END) +{ +} + +XnIRProcessor::~XnIRProcessor() +{ +} + +XnStatus XnIRProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnFrameStreamProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_INPUT_ELEMENT_SIZE); + + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE16: + break; + case XN_OUTPUT_FORMAT_RGB24: + XN_VALIDATE_BUFFER_ALLOCATE(m_UnpackedBuffer, GetExpectedOutputSize()); + break; + } + + return (XN_STATUS_OK); +} + +XnStatus XnIRProcessor::Unpack10to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt16* pnOutput, XnUInt32* pnActualRead, XnUInt32* pnOutputSize) +{ + XnInt32 cInput = 0; + const XnUInt8* pOrigInput = pcInput; + + XnUInt32 nElements = nInputSize / XN_INPUT_ELEMENT_SIZE; // floored + XnUInt32 nNeededOutput = nElements * XN_OUTPUT_ELEMENT_SIZE; + + *pnActualRead = 0; + + if (*pnOutputSize < nNeededOutput) + { + *pnOutputSize = 0; + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + // Convert the 10bit packed data into 16bit shorts + + for (XnUInt32 nElem = 0; nElem < nElements; ++nElem) + { + //1a + cInput = *pcInput; + *pnOutput = (cInput & 0xFF) << 2; + + //1b + pcInput++; + cInput = *pcInput; + *pnOutput = *pnOutput | ((cInput & 0xC0) >> 6); + pnOutput++; + + //2a + *pnOutput = (cInput & 0x3F) << 4; + + //2b + pcInput++; + cInput = *pcInput; + *pnOutput = *pnOutput | ((cInput & 0xF0) >> 4); + pnOutput++; + + //3a + *pnOutput = (cInput & 0x0F) << 6; + + //3b + pcInput++; + cInput = *pcInput; + *pnOutput = *pnOutput | ((cInput & 0xFC) >> 2); + pnOutput++; + + //4a + *pnOutput = (cInput & 0x3) << 8; + + //4b + pcInput++; + cInput = *pcInput; + *pnOutput = *pnOutput | (cInput & 0xFF); + pnOutput++; + + pcInput++; + } + + *pnActualRead = pcInput - pOrigInput; + *pnOutputSize = nNeededOutput; + return XN_STATUS_OK; +} + +void XnIRProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnIRProcessor::ProcessFramePacketChunk") + + // if output format is Gray16, we can write directly to output buffer. otherwise, we need + // to write to a temp buffer. + XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE16) ? GetWriteBuffer() : &m_UnpackedBuffer; + + if (m_ContinuousBuffer.GetSize() != 0) + { + // fill in to a whole element + XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); + m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); + pData += nReadBytes; + nDataSize -= nReadBytes; + + if (m_ContinuousBuffer.GetSize() == XN_INPUT_ELEMENT_SIZE) + { + // process it + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + if (XN_STATUS_OK != Unpack10to16(m_ContinuousBuffer.GetData(), XN_INPUT_ELEMENT_SIZE, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), &nActualRead, &nOutputSize)) + WriteBufferOverflowed(); + else + pWriteBuffer->UnsafeUpdateSize(nOutputSize); + + m_ContinuousBuffer.Reset(); + } + } + + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + if (XN_STATUS_OK != Unpack10to16(pData, nDataSize, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), &nActualRead, &nOutputSize)) + { + WriteBufferOverflowed(); + } + else + { + pWriteBuffer->UnsafeUpdateSize(nOutputSize); + + pData += nActualRead; + nDataSize -= nActualRead; + + // if we have any bytes left, store them for next packet + if (nDataSize > 0) + { + // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE + // are left. + m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); + } + } + + XN_PROFILING_END_SECTION +} + +void IRto888(XnUInt16* pInput, XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + XnUInt16* pInputEnd = pInput + nInputSize; + XnUInt8* pOutputOrig = pOutput; + XnUInt8* pOutputEnd = pOutput + *pnOutputSize; + + while (pInput != pInputEnd && pOutput < pOutputEnd) + { + *pOutput = (*pInput)>>2; + *(pOutput+1) = *pOutput; + *(pOutput+2) = *pOutput; + + pOutput+=3; + pInput++; + } + + *pnOutputSize = pOutput - pOutputOrig; +} + +XnUInt32 XnIRProcessor::CalculateExpectedSize() +{ + XnUInt32 nXRes = GetStream()->GetXRes(); + XnUInt32 nYRes = GetStream()->GetYRes(); + + // when cropping is turned on, actual depth size is smaller + if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) + { + nXRes = (XnUInt32)GetStream()->m_FirmwareCropSizeX.GetValue(); + nYRes = (XnUInt32)GetStream()->m_FirmwareCropSizeY.GetValue(); + } + else if (GetStream()->GetResolution() != XN_RESOLUTION_SXGA) + { + // there are additional 8 rows + nYRes += 8; + } + + return nXRes * nYRes * GetStream()->GetBytesPerPixel(); +} + +void XnIRProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XN_PROFILING_START_SECTION("XnIRProcessor::OnEndOfFrame") + + // if there are bytes left in continuous buffer, then we have a corrupt frame + if (m_ContinuousBuffer.GetSize() != 0) + { + xnLogWarning(XN_MASK_SENSOR_READ, "IR buffer is corrupt. There are left over bytes (invalid size)"); + FrameIsCorrupted(); + } + + // if data was written to temp buffer, convert it now + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE16: + break; + case XN_OUTPUT_FORMAT_RGB24: + { + XnUInt32 nOutputSize = GetWriteBuffer()->GetFreeSpaceInBuffer(); + IRto888((XnUInt16*)m_UnpackedBuffer.GetData(), m_UnpackedBuffer.GetSize() / sizeof(XnUInt16), GetWriteBuffer()->GetUnsafeWritePointer(), &nOutputSize); + GetWriteBuffer()->UnsafeUpdateSize(nOutputSize); + m_UnpackedBuffer.Reset(); + } + break; + } + + XnUInt32 nExpectedBufferSize = CalculateExpectedSize(); + if (GetWriteBuffer()->GetSize() != nExpectedBufferSize) + { + xnLogWarning(XN_MASK_SENSOR_READ, "IR buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedBufferSize); + FrameIsCorrupted(); + } + + XnFrameStreamProcessor::OnEndOfFrame(pHeader); + m_ContinuousBuffer.Reset(); + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnIRProcessor.h b/Source/XnDeviceSensorV2/XnIRProcessor.h index 3df8f59..8588793 100644 --- a/Source/XnDeviceSensorV2/XnIRProcessor.h +++ b/Source/XnDeviceSensorV2/XnIRProcessor.h @@ -1,75 +1,75 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IR_PROCESSOR_H__ -#define __XN_IR_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameStreamProcessor.h" -#include "XnSensorIRStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnIRProcessor : public XnFrameStreamProcessor -{ -public: - XnIRProcessor(XnSensorIRStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnIRProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Internal Functions - //--------------------------------------------------------------------------- -private: - XnUInt32 CalculateExpectedSize(); - XnStatus Unpack10to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt16* pnOutput, XnUInt32* pnActualRead, XnUInt32* pnOutputSize); - inline XnSensorIRStream* GetStream() - { - return (XnSensorIRStream*)XnFrameStreamProcessor::GetStream(); - } - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - /* A buffer to store bytes till we have enough to unpack. */ - XnBuffer m_ContinuousBuffer; - XnBuffer m_UnpackedBuffer; -}; - -#endif //__XN_IR_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IR_PROCESSOR_H__ +#define __XN_IR_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameStreamProcessor.h" +#include "XnSensorIRStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnIRProcessor : public XnFrameStreamProcessor +{ +public: + XnIRProcessor(XnSensorIRStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnIRProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Internal Functions + //--------------------------------------------------------------------------- +private: + XnUInt32 CalculateExpectedSize(); + XnStatus Unpack10to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt16* pnOutput, XnUInt32* pnActualRead, XnUInt32* pnOutputSize); + inline XnSensorIRStream* GetStream() + { + return (XnSensorIRStream*)XnFrameStreamProcessor::GetStream(); + } + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + /* A buffer to store bytes till we have enough to unpack. */ + XnBuffer m_ContinuousBuffer; + XnBuffer m_UnpackedBuffer; +}; + +#endif //__XN_IR_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnImageProcessor.cpp b/Source/XnDeviceSensorV2/XnImageProcessor.cpp index 536fe0f..c93daac 100644 --- a/Source/XnDeviceSensorV2/XnImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnImageProcessor.cpp @@ -1,136 +1,136 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" -#include "XnSensor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnImageProcessor::XnImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END) -{ -} - -XnImageProcessor::~XnImageProcessor() -{ - // unregister from properties (otherwise, callbacks will be called with deleted pointer...) - GetStream()->XResProperty().OnChangeEvent().Unregister(m_hXResCallback); - GetStream()->YResProperty().OnChangeEvent().Unregister(m_hYResCallback); - GetStream()->m_FirmwareCropSizeX.OnChangeEvent().Unregister(m_hXCropCallback); - GetStream()->m_FirmwareCropSizeY.OnChangeEvent().Unregister(m_hYCropCallback); - GetStream()->m_FirmwareCropEnabled.OnChangeEvent().Unregister(m_hCropEnabledCallback); -} - -XnStatus XnImageProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnFrameStreamProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->XResProperty().OnChangeEvent().Register(ActualResChangedCallback, this, &m_hXResCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->YResProperty().OnChangeEvent().Register(ActualResChangedCallback, this, &m_hYResCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->m_FirmwareCropSizeX.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hXCropCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->m_FirmwareCropSizeY.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hYCropCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetStream()->m_FirmwareCropEnabled.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hCropEnabledCallback); - XN_IS_STATUS_OK(nRetVal); - - CalcActualRes(); - - return (XN_STATUS_OK); -} - -XnUInt32 XnImageProcessor::CalculateExpectedSize() -{ - XnUInt32 nExpectedDepthBufferSize = GetStream()->GetXRes() * GetStream()->GetYRes(); - - // when cropping is turned on, actual depth size is smaller - if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) - { - nExpectedDepthBufferSize = (XnUInt32)(GetStream()->m_FirmwareCropSizeX.GetValue() * GetStream()->m_FirmwareCropSizeY.GetValue()); - } - - nExpectedDepthBufferSize *= GetStream()->GetBytesPerPixel(); - - return nExpectedDepthBufferSize; -} - -void XnImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnUInt32 nExpectedSize = CalculateExpectedSize(); - if (GetWriteBuffer()->GetSize() != nExpectedSize) - { - xnLogWarning(XN_MASK_SENSOR_READ, "Read: Image buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedSize); - FrameIsCorrupted(); - } - - // call base - XnFrameStreamProcessor::OnEndOfFrame(pHeader); -} - -void XnImageProcessor::OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) -{ - XnFrameStreamProcessor::OnFrameReady(nFrameID, nFrameTS); - - m_pDevicePrivateData->pSensor->GetFPSCalculator()->MarkInputImage(nFrameID, nFrameTS); -} - -void XnImageProcessor::CalcActualRes() -{ - if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) - { - m_nActualXRes = (XnUInt32)GetStream()->m_FirmwareCropSizeX.GetValue(); - m_nActualYRes = (XnUInt32)GetStream()->m_FirmwareCropSizeY.GetValue(); - } - else - { - m_nActualXRes = GetStream()->GetXRes(); - m_nActualYRes = GetStream()->GetYRes(); - } -} - -XnStatus XnImageProcessor::ActualResChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnImageProcessor* pThis = (XnImageProcessor*)pCookie; - pThis->CalcActualRes(); - return XN_STATUS_OK; -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" +#include "XnSensor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnImageProcessor::XnImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnFrameStreamProcessor(pStream, pHelper, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_START, XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END) +{ +} + +XnImageProcessor::~XnImageProcessor() +{ + // unregister from properties (otherwise, callbacks will be called with deleted pointer...) + GetStream()->XResProperty().OnChangeEvent().Unregister(m_hXResCallback); + GetStream()->YResProperty().OnChangeEvent().Unregister(m_hYResCallback); + GetStream()->m_FirmwareCropSizeX.OnChangeEvent().Unregister(m_hXCropCallback); + GetStream()->m_FirmwareCropSizeY.OnChangeEvent().Unregister(m_hYCropCallback); + GetStream()->m_FirmwareCropEnabled.OnChangeEvent().Unregister(m_hCropEnabledCallback); +} + +XnStatus XnImageProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnFrameStreamProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->XResProperty().OnChangeEvent().Register(ActualResChangedCallback, this, &m_hXResCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->YResProperty().OnChangeEvent().Register(ActualResChangedCallback, this, &m_hYResCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->m_FirmwareCropSizeX.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hXCropCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->m_FirmwareCropSizeY.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hYCropCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetStream()->m_FirmwareCropEnabled.OnChangeEvent().Register(ActualResChangedCallback, this, &m_hCropEnabledCallback); + XN_IS_STATUS_OK(nRetVal); + + CalcActualRes(); + + return (XN_STATUS_OK); +} + +XnUInt32 XnImageProcessor::CalculateExpectedSize() +{ + XnUInt32 nExpectedDepthBufferSize = GetStream()->GetXRes() * GetStream()->GetYRes(); + + // when cropping is turned on, actual depth size is smaller + if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) + { + nExpectedDepthBufferSize = (XnUInt32)(GetStream()->m_FirmwareCropSizeX.GetValue() * GetStream()->m_FirmwareCropSizeY.GetValue()); + } + + nExpectedDepthBufferSize *= GetStream()->GetBytesPerPixel(); + + return nExpectedDepthBufferSize; +} + +void XnImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnUInt32 nExpectedSize = CalculateExpectedSize(); + if (GetWriteBuffer()->GetSize() != nExpectedSize) + { + xnLogWarning(XN_MASK_SENSOR_READ, "Read: Image buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedSize); + FrameIsCorrupted(); + } + + // call base + XnFrameStreamProcessor::OnEndOfFrame(pHeader); +} + +void XnImageProcessor::OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS) +{ + XnFrameStreamProcessor::OnFrameReady(nFrameID, nFrameTS); + + m_pDevicePrivateData->pSensor->GetFPSCalculator()->MarkInputImage(nFrameID, nFrameTS); +} + +void XnImageProcessor::CalcActualRes() +{ + if (GetStream()->m_FirmwareCropEnabled.GetValue() == TRUE) + { + m_nActualXRes = (XnUInt32)GetStream()->m_FirmwareCropSizeX.GetValue(); + m_nActualYRes = (XnUInt32)GetStream()->m_FirmwareCropSizeY.GetValue(); + } + else + { + m_nActualXRes = GetStream()->GetXRes(); + m_nActualYRes = GetStream()->GetYRes(); + } +} + +XnStatus XnImageProcessor::ActualResChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnImageProcessor* pThis = (XnImageProcessor*)pCookie; + pThis->CalcActualRes(); + return XN_STATUS_OK; +} + diff --git a/Source/XnDeviceSensorV2/XnImageProcessor.h b/Source/XnDeviceSensorV2/XnImageProcessor.h index 7d6c32e..159aa73 100644 --- a/Source/XnDeviceSensorV2/XnImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnImageProcessor.h @@ -1,80 +1,80 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_IMAGE_PROCESSOR_H__ -#define __XN_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFrameStreamProcessor.h" -#include "XnSensorImageStream.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -class XnImageProcessor : public XnFrameStreamProcessor -{ -public: - XnImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnImageProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS); - - //--------------------------------------------------------------------------- - // Helper Functions - //--------------------------------------------------------------------------- - inline XnSensorImageStream* GetStream() - { - return (XnSensorImageStream*)XnFrameStreamProcessor::GetStream(); - } - - XnUInt32 GetActualXRes() { return m_nActualXRes; } - XnUInt32 GetActualYRes() { return m_nActualYRes; } - -private: - XnUInt32 CalculateExpectedSize(); - void CalcActualRes(); - static XnStatus XN_CALLBACK_TYPE ActualResChangedCallback(const XnProperty* pSender, void* pCookie); - - XnUInt32 m_nActualXRes; - XnUInt32 m_nActualYRes; - - XnCallbackHandle m_hXResCallback; - XnCallbackHandle m_hYResCallback; - XnCallbackHandle m_hXCropCallback; - XnCallbackHandle m_hYCropCallback; - XnCallbackHandle m_hCropEnabledCallback; -}; - -#endif //__XN_IMAGE_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_IMAGE_PROCESSOR_H__ +#define __XN_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFrameStreamProcessor.h" +#include "XnSensorImageStream.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +class XnImageProcessor : public XnFrameStreamProcessor +{ +public: + XnImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnImageProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnFrameReady(XnUInt32 nFrameID, XnUInt64 nFrameTS); + + //--------------------------------------------------------------------------- + // Helper Functions + //--------------------------------------------------------------------------- + inline XnSensorImageStream* GetStream() + { + return (XnSensorImageStream*)XnFrameStreamProcessor::GetStream(); + } + + XnUInt32 GetActualXRes() { return m_nActualXRes; } + XnUInt32 GetActualYRes() { return m_nActualYRes; } + +private: + XnUInt32 CalculateExpectedSize(); + void CalcActualRes(); + static XnStatus XN_CALLBACK_TYPE ActualResChangedCallback(const XnProperty* pSender, void* pCookie); + + XnUInt32 m_nActualXRes; + XnUInt32 m_nActualYRes; + + XnCallbackHandle m_hXResCallback; + XnCallbackHandle m_hYResCallback; + XnCallbackHandle m_hXCropCallback; + XnCallbackHandle m_hYCropCallback; + XnCallbackHandle m_hCropEnabledCallback; +}; + +#endif //__XN_IMAGE_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnJpegImageProcessor.cpp b/Source/XnDeviceSensorV2/XnJpegImageProcessor.cpp index 3d9b91b..711d620 100644 --- a/Source/XnDeviceSensorV2/XnJpegImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnJpegImageProcessor.cpp @@ -1,114 +1,114 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnJpegImageProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnJpegImageProcessor::XnJpegImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnJpegImageProcessor::~XnJpegImageProcessor() -{ - XnStreamFreeUncompressImageJ(&m_JPEGContext); -} - -XnStatus XnJpegImageProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnImageProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_RawData, GetExpectedOutputSize()); - - nRetVal = XnStreamInitUncompressImageJ(&m_JPEGContext); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnJpegImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnJpegImageProcessor::ProcessFramePacketChunk") - - // append to raw buffer - if (m_RawData.GetFreeSpaceInBuffer() < nDataSize) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Bad overflow image! %d", m_RawData.GetSize()); - FrameIsCorrupted(); - m_RawData.Reset(); - } - else - { - m_RawData.UnsafeWrite(pData, nDataSize); - } - - XN_PROFILING_END_SECTION -} - -void XnJpegImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnImageProcessor::OnStartOfFrame(pHeader); - m_RawData.Reset(); -} - -void XnJpegImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XN_PROFILING_START_SECTION("XnJpegImageProcessor::OnEndOfFrame") - - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - XnUInt32 nOutputSize = pWriteBuffer->GetMaxSize(); - XnStatus nRetVal = XnStreamUncompressImageJ(&m_JPEGContext, m_RawData.GetData(), m_RawData.GetSize(), pWriteBuffer->GetUnsafeWritePointer(), &nOutputSize); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Failed to uncompress JPEG for frame %d: %s (%d)\n", GetCurrentFrameID(), xnGetStatusString(nRetVal), pWriteBuffer->GetSize()); - FrameIsCorrupted(); - - XnDump badImageDump = XN_DUMP_CLOSED; - xnDumpInit(&badImageDump, XN_DUMP_BAD_IMAGE, NULL, "BadImage_%d.jpeg", GetCurrentFrameID()); - xnDumpWriteBuffer(badImageDump, m_RawData.GetData(), m_RawData.GetSize()); - xnDumpClose(&badImageDump); - } - - pWriteBuffer->UnsafeUpdateSize(nOutputSize); - - m_RawData.Reset(); - XnImageProcessor::OnEndOfFrame(pHeader); - - XN_PROFILING_END_SECTION -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnJpegImageProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnJpegImageProcessor::XnJpegImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnJpegImageProcessor::~XnJpegImageProcessor() +{ + XnStreamFreeUncompressImageJ(&m_JPEGContext); +} + +XnStatus XnJpegImageProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnImageProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_RawData, GetExpectedOutputSize()); + + nRetVal = XnStreamInitUncompressImageJ(&m_JPEGContext); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnJpegImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnJpegImageProcessor::ProcessFramePacketChunk") + + // append to raw buffer + if (m_RawData.GetFreeSpaceInBuffer() < nDataSize) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Bad overflow image! %d", m_RawData.GetSize()); + FrameIsCorrupted(); + m_RawData.Reset(); + } + else + { + m_RawData.UnsafeWrite(pData, nDataSize); + } + + XN_PROFILING_END_SECTION +} + +void XnJpegImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnImageProcessor::OnStartOfFrame(pHeader); + m_RawData.Reset(); +} + +void XnJpegImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XN_PROFILING_START_SECTION("XnJpegImageProcessor::OnEndOfFrame") + + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + XnUInt32 nOutputSize = pWriteBuffer->GetMaxSize(); + XnStatus nRetVal = XnStreamUncompressImageJ(&m_JPEGContext, m_RawData.GetData(), m_RawData.GetSize(), pWriteBuffer->GetUnsafeWritePointer(), &nOutputSize); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Failed to uncompress JPEG for frame %d: %s (%d)\n", GetCurrentFrameID(), xnGetStatusString(nRetVal), pWriteBuffer->GetSize()); + FrameIsCorrupted(); + + XnDump badImageDump = XN_DUMP_CLOSED; + xnDumpInit(&badImageDump, XN_DUMP_BAD_IMAGE, NULL, "BadImage_%d.jpeg", GetCurrentFrameID()); + xnDumpWriteBuffer(badImageDump, m_RawData.GetData(), m_RawData.GetSize()); + xnDumpClose(&badImageDump); + } + + pWriteBuffer->UnsafeUpdateSize(nOutputSize); + + m_RawData.Reset(); + XnImageProcessor::OnEndOfFrame(pHeader); + + XN_PROFILING_END_SECTION +} + diff --git a/Source/XnDeviceSensorV2/XnJpegImageProcessor.h b/Source/XnDeviceSensorV2/XnJpegImageProcessor.h index b01356c..d8e4b3e 100644 --- a/Source/XnDeviceSensorV2/XnJpegImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnJpegImageProcessor.h @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_JPEG_IMAGE_PROCESSOR_H__ -#define __XN_JPEG_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnJpegImageProcessor : public XnImageProcessor -{ -public: - XnJpegImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnJpegImageProcessor(); - - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - XnBuffer m_RawData; - XnStreamUncompJPEGContext m_JPEGContext; -}; - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_JPEG_IMAGE_PROCESSOR_H__ +#define __XN_JPEG_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnJpegImageProcessor : public XnImageProcessor +{ +public: + XnJpegImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnJpegImageProcessor(); + + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + XnBuffer m_RawData; + XnStreamUncompJPEGContext m_JPEGContext; +}; + +#endif diff --git a/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.cpp b/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.cpp index 44e9f9b..d9e77d0 100644 --- a/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.cpp +++ b/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.cpp @@ -1,108 +1,108 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnMultiPropChangedHandler.h" - -//--------------------------------------------------------------------------- -// XnMultiPropChangedHandler Helper Class -//--------------------------------------------------------------------------- -XnMultiPropChangedHandler::XnMultiPropChangedHandler(XnSensorProductionNode* pNode, const XnChar* strModule) : - m_pNode(pNode), - m_strModule((strModule != NULL) ? strModule : pNode->GetModuleName()) -{} - -XnMultiPropChangedHandler::~XnMultiPropChangedHandler() -{ - // we cannot assume node or sensor still exist, so don't unregister. -} - -XnStatus XnMultiPropChangedHandler::AddProperty(const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnCallbackHandle hCallback; - nRetVal = m_pNode->GetSensor()->RegisterToPropertyChange(m_strModule, strName, PropertyChangedCallback, this, &hCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Registered.Set(strName, hCallback); - if (nRetVal != XN_STATUS_OK) - { - m_pNode->GetSensor()->UnregisterFromPropertyChange(m_strModule, strName, hCallback); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnMultiPropChangedHandler::AddProperties(const XnChar** strNames) -{ - XnStatus nRetVal = XN_STATUS_OK; - - const XnChar** pstrName = strNames; - - while (*pstrName != NULL) - { - nRetVal = AddProperty(*pstrName); - XN_IS_STATUS_OK(nRetVal); - - ++pstrName; - } - - return (XN_STATUS_OK); -} - -void XnMultiPropChangedHandler::Unregister() -{ - for (XnPropertyHandleHash::Iterator it = m_Registered.begin(); it != m_Registered.end(); ++it) - { - m_pNode->GetSensor()->UnregisterFromPropertyChange(m_strModule, it.Key(), it.Value()); - } -} - -void XnMultiPropChangedHandler::PropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie) -{ - XnMultiPropChangedHandler* pThis = (XnMultiPropChangedHandler*)pCookie; - pThis->OnModulePropertyChanged(ModuleName, PropertyName); -} - -//--------------------------------------------------------------------------- -// XnMultiPropStateChangedHandler -//--------------------------------------------------------------------------- -XnMultiPropStateChangedHandler::XnMultiPropStateChangedHandler(XnSensorProductionNode* pNode, XnModuleStateChangedHandler handler, void* pCookie, const XnChar* strModule /* = NULL */) : - XnMultiPropChangedHandler(pNode, strModule), - m_pHandler(handler), - m_pCookie(pCookie) -{} - -void XnMultiPropStateChangedHandler::OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty) -{ - m_pHandler(m_pCookie); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnMultiPropChangedHandler.h" + +//--------------------------------------------------------------------------- +// XnMultiPropChangedHandler Helper Class +//--------------------------------------------------------------------------- +XnMultiPropChangedHandler::XnMultiPropChangedHandler(XnSensorProductionNode* pNode, const XnChar* strModule) : + m_pNode(pNode), + m_strModule((strModule != NULL) ? strModule : pNode->GetModuleName()) +{} + +XnMultiPropChangedHandler::~XnMultiPropChangedHandler() +{ + // we cannot assume node or sensor still exist, so don't unregister. +} + +XnStatus XnMultiPropChangedHandler::AddProperty(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnCallbackHandle hCallback; + nRetVal = m_pNode->GetSensor()->RegisterToPropertyChange(m_strModule, strName, PropertyChangedCallback, this, &hCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Registered.Set(strName, hCallback); + if (nRetVal != XN_STATUS_OK) + { + m_pNode->GetSensor()->UnregisterFromPropertyChange(m_strModule, strName, hCallback); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnMultiPropChangedHandler::AddProperties(const XnChar** strNames) +{ + XnStatus nRetVal = XN_STATUS_OK; + + const XnChar** pstrName = strNames; + + while (*pstrName != NULL) + { + nRetVal = AddProperty(*pstrName); + XN_IS_STATUS_OK(nRetVal); + + ++pstrName; + } + + return (XN_STATUS_OK); +} + +void XnMultiPropChangedHandler::Unregister() +{ + for (XnPropertyHandleHash::Iterator it = m_Registered.begin(); it != m_Registered.end(); ++it) + { + m_pNode->GetSensor()->UnregisterFromPropertyChange(m_strModule, it.Key(), it.Value()); + } +} + +void XnMultiPropChangedHandler::PropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie) +{ + XnMultiPropChangedHandler* pThis = (XnMultiPropChangedHandler*)pCookie; + pThis->OnModulePropertyChanged(ModuleName, PropertyName); +} + +//--------------------------------------------------------------------------- +// XnMultiPropStateChangedHandler +//--------------------------------------------------------------------------- +XnMultiPropStateChangedHandler::XnMultiPropStateChangedHandler(XnSensorProductionNode* pNode, XnModuleStateChangedHandler handler, void* pCookie, const XnChar* strModule /* = NULL */) : + XnMultiPropChangedHandler(pNode, strModule), + m_pHandler(handler), + m_pCookie(pCookie) +{} + +void XnMultiPropStateChangedHandler::OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty) +{ + m_pHandler(m_pCookie); +} + diff --git a/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.h b/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.h index 2ce68b5..7c54e81 100644 --- a/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.h +++ b/Source/XnDeviceSensorV2/XnMultiPropChangedHandler.h @@ -1,83 +1,83 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_MULTI_PROP_CHANGED_HANDLER_H__ -#define __XN_MULTI_PROP_CHANGED_HANDLER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnSensorProductionNode.h" -#include - -//--------------------------------------------------------------------------- -// XnMultiPropChangedHandler -//--------------------------------------------------------------------------- -class XnMultiPropChangedHandler -{ -public: - XnMultiPropChangedHandler(XnSensorProductionNode* pNode, const XnChar* strModule = NULL); - virtual ~XnMultiPropChangedHandler(); - - XnStatus AddProperty(const XnChar* strName); - XnStatus AddProperties(const XnChar** strNames); - - void Unregister(); - -protected: - virtual void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty) = 0; - -private: - static void XN_CALLBACK_TYPE PropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); - - XN_DECLARE_STRINGS_HASH(XnCallbackHandle, XnPropertyHandleHash); - - XnPropertyHandleHash m_Registered; - XnSensorProductionNode* m_pNode; - const XnChar* m_strModule; -}; - -//--------------------------------------------------------------------------- -// XnMultiPropStateChangedHandler -//--------------------------------------------------------------------------- -class XnMultiPropStateChangedHandler : public XnMultiPropChangedHandler -{ -public: - XnMultiPropStateChangedHandler(XnSensorProductionNode* pNode, XnModuleStateChangedHandler handler, void* pCookie, const XnChar* strModule = NULL); - -protected: - virtual void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty); - -private: - XnModuleStateChangedHandler m_pHandler; - void* m_pCookie; -}; - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_MULTI_PROP_CHANGED_HANDLER_H__ +#define __XN_MULTI_PROP_CHANGED_HANDLER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnSensorProductionNode.h" +#include + +//--------------------------------------------------------------------------- +// XnMultiPropChangedHandler +//--------------------------------------------------------------------------- +class XnMultiPropChangedHandler +{ +public: + XnMultiPropChangedHandler(XnSensorProductionNode* pNode, const XnChar* strModule = NULL); + virtual ~XnMultiPropChangedHandler(); + + XnStatus AddProperty(const XnChar* strName); + XnStatus AddProperties(const XnChar** strNames); + + void Unregister(); + +protected: + virtual void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty) = 0; + +private: + static void XN_CALLBACK_TYPE PropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); + + XN_DECLARE_STRINGS_HASH(XnCallbackHandle, XnPropertyHandleHash); + + XnPropertyHandleHash m_Registered; + XnSensorProductionNode* m_pNode; + const XnChar* m_strModule; +}; + +//--------------------------------------------------------------------------- +// XnMultiPropStateChangedHandler +//--------------------------------------------------------------------------- +class XnMultiPropStateChangedHandler : public XnMultiPropChangedHandler +{ +public: + XnMultiPropStateChangedHandler(XnSensorProductionNode* pNode, XnModuleStateChangedHandler handler, void* pCookie, const XnChar* strModule = NULL); + +protected: + virtual void OnModulePropertyChanged(const XnChar* strModule, const XnChar* strProperty); + +private: + XnModuleStateChangedHandler m_pHandler; + void* m_pCookie; +}; + + #endif // __XN_MULTI_PROP_CHANGED_HANDLER_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.cpp b/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.cpp index 1ed1ad0..134de84 100644 --- a/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.cpp @@ -1,302 +1,302 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnPSCompressedDepthProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnPSCompressedDepthProcessor::XnPSCompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : - XnDepthProcessor(pStream, pHelper) -{ -} - -XnStatus XnPSCompressedDepthProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDepthProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_RawData, GetExpectedOutputSize()); - - return XN_STATUS_OK; -} - -XnPSCompressedDepthProcessor::~XnPSCompressedDepthProcessor() -{ -} - -#define XN_CHECK_UNC_DEPTH_OUTPUT(x, y, z) \ - if (x >= y) \ - { \ - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); \ - } \ - if (z >= XN_DEVICE_SENSOR_MAX_SHIFT_VALUE) \ - { \ - z = XN_DEVICE_SENSOR_NO_DEPTH_VALUE; \ - } - -#define XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nValue) \ - XN_CHECK_UNC_DEPTH_OUTPUT(pOutput, pOutputEnd, nValue) \ - *pOutput = GetOutput(nValue); \ - ++pOutput; - -#define INIT_INPUT(pInput, nInputSize) \ - const XnUInt8* __pInputOrig = pInput; \ - const XnUInt8* __pCurrInput = pInput; \ - const XnUInt8* __pInputEnd = pInput + nInputSize; \ - XnBool __bShouldReadByte = TRUE; \ - XnUInt32 __nLastByte = 0; - -#define GET_NEXT_INPUT(nInput) \ - if (__bShouldReadByte) \ - { \ - if (__pCurrInput == __pInputEnd) \ - break; \ - \ - /* read from input */ \ - __nLastByte = *__pCurrInput; \ - __bShouldReadByte = FALSE; \ - \ - /* take high 4-bits */ \ - nInput = __nLastByte >> 4; \ - \ - __pCurrInput++; \ - } \ - else \ - { \ - /* byte already read. take its low 4-bits */ \ - nInput = __nLastByte & 0x0F; \ - __bShouldReadByte = TRUE; \ - } - -/** True if input is in a steady state (not in the middle of a byte) */ -#define CAN_INPUT_STOP_HERE __bShouldReadByte - -/** Gets a pointer to n elements before current input */ -#define GET_PREV_INPUT(n) __pCurrInput - n/2; - -#define GET_INPUT_READ_BYTES __pCurrInput - __pInputOrig; - -XnStatus XnPSCompressedDepthProcessor::UncompressDepthPS(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt16* pOutput, XnUInt32* pnOutputSize, - XnUInt32* pnActualRead, XnBool bLastPart) -{ - // Input is made of 4-bit elements. - INIT_INPUT(pInput, nInputSize); - - XnUInt16* pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); - XnUInt16 nLastValue = 0; - - const XnUInt8* pInputOrig = pInput; - XnUInt16* pOutputOrig = pOutput; - - const XnUInt8* pInputLastPossibleStop = pInputOrig; - XnUInt16* pOutputLastPossibleStop = pOutputOrig; - - // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) - XnUInt32 nInput; - XnUInt32 nLargeValue; - XnBool bCanStop; - - while (TRUE) - { - bCanStop = CAN_INPUT_STOP_HERE; - GET_NEXT_INPUT(nInput); - - switch (nInput) - { - case 0xd: // Dummy. - // Do nothing - break; - case 0xe: // RLE - // read count - GET_NEXT_INPUT(nInput); - - // should repeat last value (nInput + 1) times - nInput++; - while (nInput != 0) - { - XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); - --nInput; - } - break; - - case 0xf: // Full (or large) - // read next element - GET_NEXT_INPUT(nInput); - - // First bit tells us if it's a large diff (turned on) or a full value (turned off) - if (nInput & 0x8) // large diff (7-bit) - { - // turn off high bit, and shift left - nLargeValue = (nInput - 0x8) << 4; - - // read low 4-bits - GET_NEXT_INPUT(nInput); - - nLargeValue |= nInput; - // diff values are from -64 to 63 (0x00 to 0x7f) - nLastValue += nLargeValue - 64; - } - else // Full value (15-bit) - { - if (bCanStop) - { - // We can stop here. First input is a full value - pInputLastPossibleStop = GET_PREV_INPUT(2); - pOutputLastPossibleStop = pOutput; - } - - nLargeValue = (nInput << 12); - - // read 3 more elements - GET_NEXT_INPUT(nInput); - nLargeValue |= nInput << 8; - - GET_NEXT_INPUT(nInput); - nLargeValue |= nInput << 4; - - GET_NEXT_INPUT(nInput); - nLastValue = (nLargeValue | nInput); - } - - XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); - - break; - default: // all rest (smaller than 0xd) are diffs - // diff values are from -6 to 6 (0x0 to 0xc) - nLastValue += nInput - 6; - XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); - } - } - - if (bLastPart == TRUE) - { - *pnOutputSize = (pOutput - pOutputOrig) * sizeof(XnUInt16); - *pnActualRead = GET_INPUT_READ_BYTES; - } - else - { - *pnOutputSize = (pOutputLastPossibleStop - pOutputOrig) * sizeof(XnUInt16); - *pnActualRead = (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); - } - - // All is good... - return (XN_STATUS_OK); -} - -void XnPSCompressedDepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnPSCompressedDepthProcessor::ProcessFramePacketChunk") - - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - const XnUChar* pBuf = NULL; - XnUInt32 nBufSize = 0; - - // check if we have bytes stored from previous calls - if (m_RawData.GetSize() > 0) - { - // we have no choice. We need to append current buffer to previous bytes - if (m_RawData.GetFreeSpaceInBuffer() < nDataSize) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow depth! %d", m_RawData.GetSize()); - FrameIsCorrupted(); - } - else - { - m_RawData.UnsafeWrite(pData, nDataSize); - } - - pBuf = m_RawData.GetData(); - nBufSize = m_RawData.GetSize(); - } - else - { - // we can process the data directly - pBuf = pData; - nBufSize = nDataSize; - } - - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - XnUInt32 nWrittenOutput = nOutputSize; - XnUInt32 nActualRead = 0; - XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END && (nDataOffset + nDataSize) == pHeader->nBufSize; - XnStatus nRetVal = UncompressDepthPS(pBuf, nBufSize, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), - &nWrittenOutput, &nActualRead, bLastPart); - - if (nRetVal != XN_STATUS_OK) - { - FrameIsCorrupted(); - - static XnUInt64 nLastPrinted = 0; - - XnUInt64 nCurrTime; - xnOSGetTimeStamp(&nCurrTime); - - if (nOutputSize != 0 || (nCurrTime - nLastPrinted) > 1000) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Uncompress depth failed: %s. Input Size: %u, Output Space: %u, Last Part: %d.", xnGetStatusString(nRetVal), nBufSize, nOutputSize, bLastPart); - - xnOSGetTimeStamp(&nLastPrinted); - } - } - - pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); - - nBufSize -= nActualRead; - m_RawData.Reset(); - - // if we have any bytes left, keep them for next time - if (nBufSize > 0) - { - pBuf += nActualRead; - m_RawData.UnsafeWrite(pBuf, nBufSize); - } - - XN_PROFILING_END_SECTION -} - -void XnPSCompressedDepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnDepthProcessor::OnStartOfFrame(pHeader); - m_RawData.Reset(); -} - -void XnPSCompressedDepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnDepthProcessor::OnEndOfFrame(pHeader); - m_RawData.Reset(); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnPSCompressedDepthProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnPSCompressedDepthProcessor::XnPSCompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : + XnDepthProcessor(pStream, pHelper) +{ +} + +XnStatus XnPSCompressedDepthProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDepthProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_RawData, GetExpectedOutputSize()); + + return XN_STATUS_OK; +} + +XnPSCompressedDepthProcessor::~XnPSCompressedDepthProcessor() +{ +} + +#define XN_CHECK_UNC_DEPTH_OUTPUT(x, y, z) \ + if (x >= y) \ + { \ + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); \ + } \ + if (z >= XN_DEVICE_SENSOR_MAX_SHIFT_VALUE) \ + { \ + z = XN_DEVICE_SENSOR_NO_DEPTH_VALUE; \ + } + +#define XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nValue) \ + XN_CHECK_UNC_DEPTH_OUTPUT(pOutput, pOutputEnd, nValue) \ + *pOutput = GetOutput(nValue); \ + ++pOutput; + +#define INIT_INPUT(pInput, nInputSize) \ + const XnUInt8* __pInputOrig = pInput; \ + const XnUInt8* __pCurrInput = pInput; \ + const XnUInt8* __pInputEnd = pInput + nInputSize; \ + XnBool __bShouldReadByte = TRUE; \ + XnUInt32 __nLastByte = 0; + +#define GET_NEXT_INPUT(nInput) \ + if (__bShouldReadByte) \ + { \ + if (__pCurrInput == __pInputEnd) \ + break; \ + \ + /* read from input */ \ + __nLastByte = *__pCurrInput; \ + __bShouldReadByte = FALSE; \ + \ + /* take high 4-bits */ \ + nInput = __nLastByte >> 4; \ + \ + __pCurrInput++; \ + } \ + else \ + { \ + /* byte already read. take its low 4-bits */ \ + nInput = __nLastByte & 0x0F; \ + __bShouldReadByte = TRUE; \ + } + +/** True if input is in a steady state (not in the middle of a byte) */ +#define CAN_INPUT_STOP_HERE __bShouldReadByte + +/** Gets a pointer to n elements before current input */ +#define GET_PREV_INPUT(n) __pCurrInput - n/2; + +#define GET_INPUT_READ_BYTES __pCurrInput - __pInputOrig; + +XnStatus XnPSCompressedDepthProcessor::UncompressDepthPS(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt16* pOutput, XnUInt32* pnOutputSize, + XnUInt32* pnActualRead, XnBool bLastPart) +{ + // Input is made of 4-bit elements. + INIT_INPUT(pInput, nInputSize); + + XnUInt16* pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); + XnUInt16 nLastValue = 0; + + const XnUInt8* pInputOrig = pInput; + XnUInt16* pOutputOrig = pOutput; + + const XnUInt8* pInputLastPossibleStop = pInputOrig; + XnUInt16* pOutputLastPossibleStop = pOutputOrig; + + // NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage) + XnUInt32 nInput; + XnUInt32 nLargeValue; + XnBool bCanStop; + + while (TRUE) + { + bCanStop = CAN_INPUT_STOP_HERE; + GET_NEXT_INPUT(nInput); + + switch (nInput) + { + case 0xd: // Dummy. + // Do nothing + break; + case 0xe: // RLE + // read count + GET_NEXT_INPUT(nInput); + + // should repeat last value (nInput + 1) times + nInput++; + while (nInput != 0) + { + XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); + --nInput; + } + break; + + case 0xf: // Full (or large) + // read next element + GET_NEXT_INPUT(nInput); + + // First bit tells us if it's a large diff (turned on) or a full value (turned off) + if (nInput & 0x8) // large diff (7-bit) + { + // turn off high bit, and shift left + nLargeValue = (nInput - 0x8) << 4; + + // read low 4-bits + GET_NEXT_INPUT(nInput); + + nLargeValue |= nInput; + // diff values are from -64 to 63 (0x00 to 0x7f) + nLastValue += nLargeValue - 64; + } + else // Full value (15-bit) + { + if (bCanStop) + { + // We can stop here. First input is a full value + pInputLastPossibleStop = GET_PREV_INPUT(2); + pOutputLastPossibleStop = pOutput; + } + + nLargeValue = (nInput << 12); + + // read 3 more elements + GET_NEXT_INPUT(nInput); + nLargeValue |= nInput << 8; + + GET_NEXT_INPUT(nInput); + nLargeValue |= nInput << 4; + + GET_NEXT_INPUT(nInput); + nLastValue = (nLargeValue | nInput); + } + + XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); + + break; + default: // all rest (smaller than 0xd) are diffs + // diff values are from -6 to 6 (0x0 to 0xc) + nLastValue += nInput - 6; + XN_DEPTH_OUTPUT(pOutput, pOutputEnd, nLastValue); + } + } + + if (bLastPart == TRUE) + { + *pnOutputSize = (pOutput - pOutputOrig) * sizeof(XnUInt16); + *pnActualRead = GET_INPUT_READ_BYTES; + } + else + { + *pnOutputSize = (pOutputLastPossibleStop - pOutputOrig) * sizeof(XnUInt16); + *pnActualRead = (pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8); + } + + // All is good... + return (XN_STATUS_OK); +} + +void XnPSCompressedDepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnPSCompressedDepthProcessor::ProcessFramePacketChunk") + + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + const XnUChar* pBuf = NULL; + XnUInt32 nBufSize = 0; + + // check if we have bytes stored from previous calls + if (m_RawData.GetSize() > 0) + { + // we have no choice. We need to append current buffer to previous bytes + if (m_RawData.GetFreeSpaceInBuffer() < nDataSize) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow depth! %d", m_RawData.GetSize()); + FrameIsCorrupted(); + } + else + { + m_RawData.UnsafeWrite(pData, nDataSize); + } + + pBuf = m_RawData.GetData(); + nBufSize = m_RawData.GetSize(); + } + else + { + // we can process the data directly + pBuf = pData; + nBufSize = nDataSize; + } + + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + XnUInt32 nWrittenOutput = nOutputSize; + XnUInt32 nActualRead = 0; + XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_DEPTH_END && (nDataOffset + nDataSize) == pHeader->nBufSize; + XnStatus nRetVal = UncompressDepthPS(pBuf, nBufSize, (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(), + &nWrittenOutput, &nActualRead, bLastPart); + + if (nRetVal != XN_STATUS_OK) + { + FrameIsCorrupted(); + + static XnUInt64 nLastPrinted = 0; + + XnUInt64 nCurrTime; + xnOSGetTimeStamp(&nCurrTime); + + if (nOutputSize != 0 || (nCurrTime - nLastPrinted) > 1000) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Uncompress depth failed: %s. Input Size: %u, Output Space: %u, Last Part: %d.", xnGetStatusString(nRetVal), nBufSize, nOutputSize, bLastPart); + + xnOSGetTimeStamp(&nLastPrinted); + } + } + + pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); + + nBufSize -= nActualRead; + m_RawData.Reset(); + + // if we have any bytes left, keep them for next time + if (nBufSize > 0) + { + pBuf += nActualRead; + m_RawData.UnsafeWrite(pBuf, nBufSize); + } + + XN_PROFILING_END_SECTION +} + +void XnPSCompressedDepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnDepthProcessor::OnStartOfFrame(pHeader); + m_RawData.Reset(); +} + +void XnPSCompressedDepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnDepthProcessor::OnEndOfFrame(pHeader); + m_RawData.Reset(); +} + diff --git a/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.h b/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.h index b1e162a..1fee0a0 100644 --- a/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.h +++ b/Source/XnDeviceSensorV2/XnPSCompressedDepthProcessor.h @@ -1,72 +1,72 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ -#define __XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDepthProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnPSCompressedDepthProcessor : public XnDepthProcessor -{ -public: - XnPSCompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnPSCompressedDepthProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Internal Functions - //--------------------------------------------------------------------------- - XnStatus UncompressDepthPS(const XnUInt8* pInput, const XnUInt32 nInputSize, - XnUInt16* pOutput, XnUInt32* pnOutputSize, - XnUInt32* pnActualRead, XnBool bLastPart); - -private: - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- - /* Keeps raw data in case not all bytes can be processed. */ - XnBuffer m_RawData; - - static void XN_CALLBACK_TYPE OnRequiredSizeChanged(); -}; - -#endif //__XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ +#define __XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDepthProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnPSCompressedDepthProcessor : public XnDepthProcessor +{ +public: + XnPSCompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnPSCompressedDepthProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Internal Functions + //--------------------------------------------------------------------------- + XnStatus UncompressDepthPS(const XnUInt8* pInput, const XnUInt32 nInputSize, + XnUInt16* pOutput, XnUInt32* pnOutputSize, + XnUInt32* pnActualRead, XnBool bLastPart); + +private: + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- + /* Keeps raw data in case not all bytes can be processed. */ + XnBuffer m_RawData; + + static void XN_CALLBACK_TYPE OnRequiredSizeChanged(); +}; + +#endif //__XN_PS_COMPRESSED_DEPTH_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.cpp b/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.cpp index 912c615..7fb22a1 100644 --- a/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.cpp @@ -1,166 +1,166 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnPSCompressedImageProcessor.h" -#include "Uncomp.h" -#include "YUV.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnPSCompressedImageProcessor::XnPSCompressedImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnPSCompressedImageProcessor::~XnPSCompressedImageProcessor() -{ -} - -XnStatus XnPSCompressedImageProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnImageProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, GetExpectedOutputSize()); - - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_YUV422: - break; - case XN_OUTPUT_FORMAT_RGB24: - XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedYUVBuffer, GetExpectedOutputSize()); - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); - } - - return (XN_STATUS_OK); -} - -void XnPSCompressedImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnPSCompressedImageProcessor::ProcessFramePacketChunk") - - // if output format is YUV, we can write directly to output buffer. otherwise, we need - // to write to a temp buffer. - XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_YUV422) ? GetWriteBuffer() : &m_UncompressedYUVBuffer; - - const XnUChar* pBuf = NULL; - XnUInt32 nBufSize = 0; - - // check if we have bytes stored from previous calls - if (m_ContinuousBuffer.GetSize() > 0) - { - // we have no choice. We need to append current buffer to previous bytes - if (m_ContinuousBuffer.GetFreeSpaceInBuffer() < nDataSize) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow image! %d", m_ContinuousBuffer.GetSize()); - FrameIsCorrupted(); - m_ContinuousBuffer.Reset(); - } - else - { - m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); - } - - pBuf = m_ContinuousBuffer.GetData(); - nBufSize = m_ContinuousBuffer.GetSize(); - } - else - { - // we can process the data directly - pBuf = pData; - nBufSize = nDataSize; - } - - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - XnUInt32 nWrittenOutput = nOutputSize; - XnUInt32 nActualRead = 0; - XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END && (nDataOffset + nDataSize) == pHeader->nBufSize; - XnStatus nRetVal = XnStreamUncompressYUVImagePS(pBuf, nBufSize, pWriteBuffer->GetUnsafeWritePointer(), - &nWrittenOutput, GetActualXRes()*2, &nActualRead, bLastPart); - - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Image decompression failed: %s (%d of %d, requested %d, last %d)", xnGetStatusString(nRetVal), nWrittenOutput, nBufSize, nOutputSize, bLastPart); - FrameIsCorrupted(); - } - - pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); - - nBufSize -= nActualRead; - m_ContinuousBuffer.Reset(); - - // if we have any bytes left, keep them for next time - if (nBufSize > 0) - { - pBuf += nActualRead; - m_ContinuousBuffer.UnsafeWrite(pBuf, nBufSize); - } - - XN_PROFILING_END_SECTION -} - -void XnPSCompressedImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnImageProcessor::OnStartOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} - -void XnPSCompressedImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XN_PROFILING_START_SECTION("XnPSCompressedImageProcessor::OnEndOfFrame") - - // if data was written to temp buffer, convert it now - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_YUV422: - break; - case XN_OUTPUT_FORMAT_RGB24: - { - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = GetWriteBuffer()->GetFreeSpaceInBuffer(); - YUV422ToRGB888(m_UncompressedYUVBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), m_UncompressedYUVBuffer.GetSize(), &nActualRead, &nOutputSize); - GetWriteBuffer()->UnsafeUpdateSize(nOutputSize); - m_UncompressedYUVBuffer.Reset(); - } - break; - } - - XnImageProcessor::OnEndOfFrame(pHeader); - m_ContinuousBuffer.Reset(); - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnPSCompressedImageProcessor.h" +#include "Uncomp.h" +#include "YUV.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnPSCompressedImageProcessor::XnPSCompressedImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnPSCompressedImageProcessor::~XnPSCompressedImageProcessor() +{ +} + +XnStatus XnPSCompressedImageProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnImageProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, GetExpectedOutputSize()); + + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_YUV422: + break; + case XN_OUTPUT_FORMAT_RGB24: + XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedYUVBuffer, GetExpectedOutputSize()); + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); + } + + return (XN_STATUS_OK); +} + +void XnPSCompressedImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnPSCompressedImageProcessor::ProcessFramePacketChunk") + + // if output format is YUV, we can write directly to output buffer. otherwise, we need + // to write to a temp buffer. + XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_YUV422) ? GetWriteBuffer() : &m_UncompressedYUVBuffer; + + const XnUChar* pBuf = NULL; + XnUInt32 nBufSize = 0; + + // check if we have bytes stored from previous calls + if (m_ContinuousBuffer.GetSize() > 0) + { + // we have no choice. We need to append current buffer to previous bytes + if (m_ContinuousBuffer.GetFreeSpaceInBuffer() < nDataSize) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_DEPTH, "Bad overflow image! %d", m_ContinuousBuffer.GetSize()); + FrameIsCorrupted(); + m_ContinuousBuffer.Reset(); + } + else + { + m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); + } + + pBuf = m_ContinuousBuffer.GetData(); + nBufSize = m_ContinuousBuffer.GetSize(); + } + else + { + // we can process the data directly + pBuf = pData; + nBufSize = nDataSize; + } + + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + XnUInt32 nWrittenOutput = nOutputSize; + XnUInt32 nActualRead = 0; + XnBool bLastPart = pHeader->nType == XN_SENSOR_PROTOCOL_RESPONSE_IMAGE_END && (nDataOffset + nDataSize) == pHeader->nBufSize; + XnStatus nRetVal = XnStreamUncompressYUVImagePS(pBuf, nBufSize, pWriteBuffer->GetUnsafeWritePointer(), + &nWrittenOutput, GetActualXRes()*2, &nActualRead, bLastPart); + + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL_IMAGE, "Image decompression failed: %s (%d of %d, requested %d, last %d)", xnGetStatusString(nRetVal), nWrittenOutput, nBufSize, nOutputSize, bLastPart); + FrameIsCorrupted(); + } + + pWriteBuffer->UnsafeUpdateSize(nWrittenOutput); + + nBufSize -= nActualRead; + m_ContinuousBuffer.Reset(); + + // if we have any bytes left, keep them for next time + if (nBufSize > 0) + { + pBuf += nActualRead; + m_ContinuousBuffer.UnsafeWrite(pBuf, nBufSize); + } + + XN_PROFILING_END_SECTION +} + +void XnPSCompressedImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnImageProcessor::OnStartOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} + +void XnPSCompressedImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XN_PROFILING_START_SECTION("XnPSCompressedImageProcessor::OnEndOfFrame") + + // if data was written to temp buffer, convert it now + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_YUV422: + break; + case XN_OUTPUT_FORMAT_RGB24: + { + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = GetWriteBuffer()->GetFreeSpaceInBuffer(); + YUV422ToRGB888(m_UncompressedYUVBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), m_UncompressedYUVBuffer.GetSize(), &nActualRead, &nOutputSize); + GetWriteBuffer()->UnsafeUpdateSize(nOutputSize); + m_UncompressedYUVBuffer.Reset(); + } + break; + } + + XnImageProcessor::OnEndOfFrame(pHeader); + m_ContinuousBuffer.Reset(); + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.h b/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.h index 7eb9293..8dd4d3e 100644 --- a/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnPSCompressedImageProcessor.h @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ -#define __XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnPSCompressedImageProcessor : public XnImageProcessor -{ -public: - XnPSCompressedImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnPSCompressedImageProcessor(); - - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - XnBuffer m_ContinuousBuffer; - XnBuffer m_UncompressedYUVBuffer; -}; - -#endif //__XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ +#define __XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnPSCompressedImageProcessor : public XnImageProcessor +{ +public: + XnPSCompressedImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnPSCompressedImageProcessor(); + + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + XnBuffer m_ContinuousBuffer; + XnBuffer m_UncompressedYUVBuffer; +}; + +#endif //__XN_PS_COMPRESSED_IMAGE_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.cpp b/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.cpp index 3f2f419..7e453ec 100644 --- a/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.cpp @@ -1,187 +1,187 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnPacked11DepthProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -/* The size of an input element in the stream. */ -#define XN_INPUT_ELEMENT_SIZE 11 -/* The size of an output element in the stream. */ -#define XN_OUTPUT_ELEMENT_SIZE 16 - -//--------------------------------------------------------------------------- -// Macros -//--------------------------------------------------------------------------- -/* Returns a set of bits. For example XN_ON_BITS(4) returns 0xF */ -#define XN_ON_BITS(count) ((1 << count)-1) - -/* Creates a mask of bits in offset */ -#define XN_CREATE_MASK(count, offset) (XN_ON_BITS(count) << offset) - -/* Takes the bits in offset from . -* For example: -* If we want 3 bits located in offset 2 from 0xF4: -* 11110100 -* --- -* we get 101, which is 0x5. -* and so, XN_TAKE_BITS(0xF4,3,2) == 0x5. -*/ -#define XN_TAKE_BITS(source, count, offset) ((source & XN_CREATE_MASK(count, offset)) >> offset) - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnPacked11DepthProcessor::XnPacked11DepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : - XnDepthProcessor(pStream, pHelper) -{ -} - -XnStatus XnPacked11DepthProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDepthProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_INPUT_ELEMENT_SIZE); - - return (XN_STATUS_OK); -} - -XnPacked11DepthProcessor::~XnPacked11DepthProcessor() -{ -} - -XnStatus XnPacked11DepthProcessor::Unpack11to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt32* pnActualRead) -{ - const XnUInt8* pOrigInput = pcInput; - - XnUInt32 nElements = nInputSize / XN_INPUT_ELEMENT_SIZE; // floored - XnUInt32 nNeededOutput = nElements * XN_OUTPUT_ELEMENT_SIZE; - - *pnActualRead = 0; - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - if (!CheckWriteBufferForOverflow(nNeededOutput)) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - XnUInt16* pnOutput = (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(); - - // Convert the 11bit packed data into 16bit shorts - for (XnUInt32 nElem = 0; nElem < nElements; ++nElem) - { - // input: 0, 1, 2,3, 4, 5, 6,7, 8, 9,10 - // -,---,---,-,---,---,---,-,---,---,- - // bits: 8,3,5,6,2,8,1,7,4,4,7,1,8,2,6,5,3,8 - // ---,---,-----,---,---,-----,---,--- - // output: 0, 1, 2, 3, 4, 5, 6, 7 - - pnOutput[0] = GetOutput((XN_TAKE_BITS(pcInput[0],8,0) << 3) | XN_TAKE_BITS(pcInput[1],3,5)); - pnOutput[1] = GetOutput((XN_TAKE_BITS(pcInput[1],5,0) << 6) | XN_TAKE_BITS(pcInput[2],6,2)); - pnOutput[2] = GetOutput((XN_TAKE_BITS(pcInput[2],2,0) << 9) | (XN_TAKE_BITS(pcInput[3],8,0) << 1) | XN_TAKE_BITS(pcInput[4],1,7)); - pnOutput[3] = GetOutput((XN_TAKE_BITS(pcInput[4],7,0) << 4) | XN_TAKE_BITS(pcInput[5],4,4)); - pnOutput[4] = GetOutput((XN_TAKE_BITS(pcInput[5],4,0) << 7) | XN_TAKE_BITS(pcInput[6],7,1)); - pnOutput[5] = GetOutput((XN_TAKE_BITS(pcInput[6],1,0) << 10) | (XN_TAKE_BITS(pcInput[7],8,0) << 2) | XN_TAKE_BITS(pcInput[8],2,6)); - pnOutput[6] = GetOutput((XN_TAKE_BITS(pcInput[8],6,0) << 5) | XN_TAKE_BITS(pcInput[9],5,3)); - pnOutput[7] = GetOutput((XN_TAKE_BITS(pcInput[9],3,0) << 8) | XN_TAKE_BITS(pcInput[10],8,0)); - - pcInput += XN_INPUT_ELEMENT_SIZE; - pnOutput += 8; - } - - *pnActualRead = pcInput - pOrigInput; - pWriteBuffer->UnsafeUpdateSize(nNeededOutput); - - return XN_STATUS_OK; -} - -void XnPacked11DepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnPacked11DepthProcessor::ProcessFramePacketChunk") - - XnStatus nRetVal = XN_STATUS_OK; - - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - // check if we have data from previous packet - if (m_ContinuousBuffer.GetSize() != 0) - { - // fill in to a whole element - XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); - m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); - pData += nReadBytes; - nDataSize -= nReadBytes; - - if (m_ContinuousBuffer.GetSize() == XN_INPUT_ELEMENT_SIZE) - { - // process it - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - Unpack11to16(m_ContinuousBuffer.GetData(), XN_INPUT_ELEMENT_SIZE, &nActualRead); - m_ContinuousBuffer.Reset(); - } - } - - // find out the number of input elements we have - XnUInt32 nActualRead = 0; - nRetVal = Unpack11to16(pData, nDataSize, &nActualRead); - if (nRetVal == XN_STATUS_OK) - { - pData += nActualRead; - nDataSize -= nActualRead; - - // if we have any bytes left, store them for next packet. - if (nDataSize > 0) - { - // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE - // are left. - m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); - } - } - - XN_PROFILING_END_SECTION -} - -void XnPacked11DepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnDepthProcessor::OnStartOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} - -void XnPacked11DepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnDepthProcessor::OnEndOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnPacked11DepthProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +/* The size of an input element in the stream. */ +#define XN_INPUT_ELEMENT_SIZE 11 +/* The size of an output element in the stream. */ +#define XN_OUTPUT_ELEMENT_SIZE 16 + +//--------------------------------------------------------------------------- +// Macros +//--------------------------------------------------------------------------- +/* Returns a set of bits. For example XN_ON_BITS(4) returns 0xF */ +#define XN_ON_BITS(count) ((1 << count)-1) + +/* Creates a mask of bits in offset */ +#define XN_CREATE_MASK(count, offset) (XN_ON_BITS(count) << offset) + +/* Takes the bits in offset from . +* For example: +* If we want 3 bits located in offset 2 from 0xF4: +* 11110100 +* --- +* we get 101, which is 0x5. +* and so, XN_TAKE_BITS(0xF4,3,2) == 0x5. +*/ +#define XN_TAKE_BITS(source, count, offset) ((source & XN_CREATE_MASK(count, offset)) >> offset) + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnPacked11DepthProcessor::XnPacked11DepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : + XnDepthProcessor(pStream, pHelper) +{ +} + +XnStatus XnPacked11DepthProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDepthProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_INPUT_ELEMENT_SIZE); + + return (XN_STATUS_OK); +} + +XnPacked11DepthProcessor::~XnPacked11DepthProcessor() +{ +} + +XnStatus XnPacked11DepthProcessor::Unpack11to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt32* pnActualRead) +{ + const XnUInt8* pOrigInput = pcInput; + + XnUInt32 nElements = nInputSize / XN_INPUT_ELEMENT_SIZE; // floored + XnUInt32 nNeededOutput = nElements * XN_OUTPUT_ELEMENT_SIZE; + + *pnActualRead = 0; + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + if (!CheckWriteBufferForOverflow(nNeededOutput)) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + XnUInt16* pnOutput = (XnUInt16*)pWriteBuffer->GetUnsafeWritePointer(); + + // Convert the 11bit packed data into 16bit shorts + for (XnUInt32 nElem = 0; nElem < nElements; ++nElem) + { + // input: 0, 1, 2,3, 4, 5, 6,7, 8, 9,10 + // -,---,---,-,---,---,---,-,---,---,- + // bits: 8,3,5,6,2,8,1,7,4,4,7,1,8,2,6,5,3,8 + // ---,---,-----,---,---,-----,---,--- + // output: 0, 1, 2, 3, 4, 5, 6, 7 + + pnOutput[0] = GetOutput((XN_TAKE_BITS(pcInput[0],8,0) << 3) | XN_TAKE_BITS(pcInput[1],3,5)); + pnOutput[1] = GetOutput((XN_TAKE_BITS(pcInput[1],5,0) << 6) | XN_TAKE_BITS(pcInput[2],6,2)); + pnOutput[2] = GetOutput((XN_TAKE_BITS(pcInput[2],2,0) << 9) | (XN_TAKE_BITS(pcInput[3],8,0) << 1) | XN_TAKE_BITS(pcInput[4],1,7)); + pnOutput[3] = GetOutput((XN_TAKE_BITS(pcInput[4],7,0) << 4) | XN_TAKE_BITS(pcInput[5],4,4)); + pnOutput[4] = GetOutput((XN_TAKE_BITS(pcInput[5],4,0) << 7) | XN_TAKE_BITS(pcInput[6],7,1)); + pnOutput[5] = GetOutput((XN_TAKE_BITS(pcInput[6],1,0) << 10) | (XN_TAKE_BITS(pcInput[7],8,0) << 2) | XN_TAKE_BITS(pcInput[8],2,6)); + pnOutput[6] = GetOutput((XN_TAKE_BITS(pcInput[8],6,0) << 5) | XN_TAKE_BITS(pcInput[9],5,3)); + pnOutput[7] = GetOutput((XN_TAKE_BITS(pcInput[9],3,0) << 8) | XN_TAKE_BITS(pcInput[10],8,0)); + + pcInput += XN_INPUT_ELEMENT_SIZE; + pnOutput += 8; + } + + *pnActualRead = pcInput - pOrigInput; + pWriteBuffer->UnsafeUpdateSize(nNeededOutput); + + return XN_STATUS_OK; +} + +void XnPacked11DepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnPacked11DepthProcessor::ProcessFramePacketChunk") + + XnStatus nRetVal = XN_STATUS_OK; + + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + // check if we have data from previous packet + if (m_ContinuousBuffer.GetSize() != 0) + { + // fill in to a whole element + XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); + m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); + pData += nReadBytes; + nDataSize -= nReadBytes; + + if (m_ContinuousBuffer.GetSize() == XN_INPUT_ELEMENT_SIZE) + { + // process it + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + Unpack11to16(m_ContinuousBuffer.GetData(), XN_INPUT_ELEMENT_SIZE, &nActualRead); + m_ContinuousBuffer.Reset(); + } + } + + // find out the number of input elements we have + XnUInt32 nActualRead = 0; + nRetVal = Unpack11to16(pData, nDataSize, &nActualRead); + if (nRetVal == XN_STATUS_OK) + { + pData += nActualRead; + nDataSize -= nActualRead; + + // if we have any bytes left, store them for next packet. + if (nDataSize > 0) + { + // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE + // are left. + m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); + } + } + + XN_PROFILING_END_SECTION +} + +void XnPacked11DepthProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnDepthProcessor::OnStartOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} + +void XnPacked11DepthProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnDepthProcessor::OnEndOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} diff --git a/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.h b/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.h index e7c634c..b7dd179 100644 --- a/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.h +++ b/Source/XnDeviceSensorV2/XnPacked11DepthProcessor.h @@ -1,68 +1,68 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_PACKED_11_DEPTH_PROCESSOR_H__ -#define __XN_PACKED_11_DEPTH_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDepthProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnPacked11DepthProcessor : public XnDepthProcessor -{ -public: - XnPacked11DepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnPacked11DepthProcessor(); - - XnStatus Init(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Internal Functions - //--------------------------------------------------------------------------- - XnStatus Unpack11to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt32* pnActualRead); - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - /* A buffer used for storing some left-over bytes for the next packet. */ - XnBuffer m_ContinuousBuffer; -}; - -#endif //__XN_PACKED_11_DEPTH_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_PACKED_11_DEPTH_PROCESSOR_H__ +#define __XN_PACKED_11_DEPTH_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDepthProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnPacked11DepthProcessor : public XnDepthProcessor +{ +public: + XnPacked11DepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnPacked11DepthProcessor(); + + XnStatus Init(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Internal Functions + //--------------------------------------------------------------------------- + XnStatus Unpack11to16(const XnUInt8* pcInput, const XnUInt32 nInputSize, XnUInt32* pnActualRead); + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + /* A buffer used for storing some left-over bytes for the next packet. */ + XnBuffer m_ContinuousBuffer; +}; + +#endif //__XN_PACKED_11_DEPTH_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnParams.h b/Source/XnDeviceSensorV2/XnParams.h index 3352f38..c2bdc31 100644 --- a/Source/XnDeviceSensorV2/XnParams.h +++ b/Source/XnDeviceSensorV2/XnParams.h @@ -1,119 +1,119 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef XN_PARAMS_H -#define XN_PARAMS_H - -typedef enum -{ - //General, - PARAM_GENERAL_CURRENT_MODE = 0, - PARAM_GENERAL_FRAME_SYNC = 1, - PARAM_GENERAL_REGISTRATION_ENABLE = 2, - PARAM_GENERAL_STREAM_PRIORITY = 3, - PARAM_GENERAL_TRIGGER_ACTION = 4, - PARAM_GENERAL_STREAM0_MODE = 5, - PARAM_GENERAL_STREAM1_MODE = 6, - //Audio, - PARAM_GENERAL_STREAM2_MODE = 7, - PARAM_AUDIO_STEREO_MODE = 8, - PARAM_AUDIO_SAMPLE_RATE = 9, - PARAM_AUDIO_LEFT_CHANNEL_VOLUME_LEVEL = 10, - PARAM_AUDIO_RIGHT_CHANNEL_VOLUME_LEVEL = 11, - //Image, - PARAM_IMAGE_FORMAT = 12, - PARAM_IMAGE_RESOLUTION = 13, - PARAM_IMAGE_FPS = 14, - PARAM_IMAGE_AGC = 15, - PARAM_IMAGE_QUALITY = 16, - PARAM_IMAGE_FLICKER_DETECTION = 17, - //Depth, - PARAM_DEPTH_FORMAT = 18, - PARAM_DEPTH_RESOLUTION = 19, - PARAM_DEPTH_FPS = 20, - PARAM_DEPTH_AGC = 21, - PARAM_DEPTH_HOLE_FILTER = 22, - PARAM_DEPTH_MIRROR = 23, - PARAM_DEPTH_DECIMATION = 24, - //IR, - PARAM_IR_FORMAT = 25, - PARAM_IR_RESOLUTION = 26, - PARAM_IR_FPS = 27, - PARAM_IR_AGC = 28, - PARAM_IR_QUALITY = 29, - //Misc, - PARAM_AUDIO_LEFT_CHANNEL_MUTE = 33, - PARAM_AUDIO_RIGHT_CHANNEL_MUTE = 34, - PARAM_AUDIO_MICROPHONE_IN = 35, - PARAM_DEPTH_GMC_MODE = 36, - PARAM_DEPTH_WHITE_BALANCE_ENABLE = 45, - - //Image Crop - PARAM_IMAGE_CROP_SIZE_X = 46, - PARAM_IMAGE_CROP_SIZE_Y = 47, - PARAM_IMAGE_CROP_OFFSET_X = 48, - PARAM_IMAGE_CROP_OFFSET_Y = 49, - PARAM_IMAGE_CROP_ENABLE = 50, - //Depth Crop - PARAM_DEPTH_CROP_SIZE_X = 51, - PARAM_DEPTH_CROP_SIZE_Y = 52, - - PARAM_DEPTH_CROP_OFFSET_X = 53, - PARAM_DEPTH_CROP_OFFSET_Y = 54, - PARAM_DEPTH_CROP_ENABLE = 55, - //IR Crop - PARAM_IR_CROP_SIZE_X = 56, - PARAM_IR_CROP_SIZE_Y = 57, - PARAM_IR_CROP_OFFSET_X = 58, - PARAM_IR_CROP_OFFSET_Y = 59, - PARAM_IR_CROP_ENABLE = 60, - - - PARAM_APC_ENABLE = 62, - - PARAM_DEPTH_AGC_BIN0_LOW = 63, - PARAM_DEPTH_AGC_BIN0_HIGH = 64, - PARAM_DEPTH_AGC_BIN1_LOW = 65, - PARAM_DEPTH_AGC_BIN1_HIGH = 66, - PARAM_DEPTH_AGC_BIN2_LOW = 67, - PARAM_DEPTH_AGC_BIN2_HIGH = 68, - PARAM_DEPTH_AGC_BIN3_LOW = 69, - PARAM_DEPTH_AGC_BIN3_HIGH = 70, - - PARAM_IMAGE_MIRROR = 71, - PARAM_IR_MIRROR = 72, - -} EConfig_Params; - -typedef enum XnExecuter -{ - XN_EXECUTER_NONE = 0, - XN_EXECUTER_FW = 1, - XN_EXECUTER_HOST = 2, -} XnExecuter; - -#endif +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef XN_PARAMS_H +#define XN_PARAMS_H + +typedef enum +{ + //General, + PARAM_GENERAL_CURRENT_MODE = 0, + PARAM_GENERAL_FRAME_SYNC = 1, + PARAM_GENERAL_REGISTRATION_ENABLE = 2, + PARAM_GENERAL_STREAM_PRIORITY = 3, + PARAM_GENERAL_TRIGGER_ACTION = 4, + PARAM_GENERAL_STREAM0_MODE = 5, + PARAM_GENERAL_STREAM1_MODE = 6, + //Audio, + PARAM_GENERAL_STREAM2_MODE = 7, + PARAM_AUDIO_STEREO_MODE = 8, + PARAM_AUDIO_SAMPLE_RATE = 9, + PARAM_AUDIO_LEFT_CHANNEL_VOLUME_LEVEL = 10, + PARAM_AUDIO_RIGHT_CHANNEL_VOLUME_LEVEL = 11, + //Image, + PARAM_IMAGE_FORMAT = 12, + PARAM_IMAGE_RESOLUTION = 13, + PARAM_IMAGE_FPS = 14, + PARAM_IMAGE_AGC = 15, + PARAM_IMAGE_QUALITY = 16, + PARAM_IMAGE_FLICKER_DETECTION = 17, + //Depth, + PARAM_DEPTH_FORMAT = 18, + PARAM_DEPTH_RESOLUTION = 19, + PARAM_DEPTH_FPS = 20, + PARAM_DEPTH_AGC = 21, + PARAM_DEPTH_HOLE_FILTER = 22, + PARAM_DEPTH_MIRROR = 23, + PARAM_DEPTH_DECIMATION = 24, + //IR, + PARAM_IR_FORMAT = 25, + PARAM_IR_RESOLUTION = 26, + PARAM_IR_FPS = 27, + PARAM_IR_AGC = 28, + PARAM_IR_QUALITY = 29, + //Misc, + PARAM_AUDIO_LEFT_CHANNEL_MUTE = 33, + PARAM_AUDIO_RIGHT_CHANNEL_MUTE = 34, + PARAM_AUDIO_MICROPHONE_IN = 35, + PARAM_DEPTH_GMC_MODE = 36, + PARAM_DEPTH_WHITE_BALANCE_ENABLE = 45, + + //Image Crop + PARAM_IMAGE_CROP_SIZE_X = 46, + PARAM_IMAGE_CROP_SIZE_Y = 47, + PARAM_IMAGE_CROP_OFFSET_X = 48, + PARAM_IMAGE_CROP_OFFSET_Y = 49, + PARAM_IMAGE_CROP_ENABLE = 50, + //Depth Crop + PARAM_DEPTH_CROP_SIZE_X = 51, + PARAM_DEPTH_CROP_SIZE_Y = 52, + + PARAM_DEPTH_CROP_OFFSET_X = 53, + PARAM_DEPTH_CROP_OFFSET_Y = 54, + PARAM_DEPTH_CROP_ENABLE = 55, + //IR Crop + PARAM_IR_CROP_SIZE_X = 56, + PARAM_IR_CROP_SIZE_Y = 57, + PARAM_IR_CROP_OFFSET_X = 58, + PARAM_IR_CROP_OFFSET_Y = 59, + PARAM_IR_CROP_ENABLE = 60, + + + PARAM_APC_ENABLE = 62, + + PARAM_DEPTH_AGC_BIN0_LOW = 63, + PARAM_DEPTH_AGC_BIN0_HIGH = 64, + PARAM_DEPTH_AGC_BIN1_LOW = 65, + PARAM_DEPTH_AGC_BIN1_HIGH = 66, + PARAM_DEPTH_AGC_BIN2_LOW = 67, + PARAM_DEPTH_AGC_BIN2_HIGH = 68, + PARAM_DEPTH_AGC_BIN3_LOW = 69, + PARAM_DEPTH_AGC_BIN3_HIGH = 70, + + PARAM_IMAGE_MIRROR = 71, + PARAM_IR_MIRROR = 72, + +} EConfig_Params; + +typedef enum XnExecuter +{ + XN_EXECUTER_NONE = 0, + XN_EXECUTER_FW = 1, + XN_EXECUTER_HOST = 2, +} XnExecuter; + +#endif diff --git a/Source/XnDeviceSensorV2/XnSensor.cpp b/Source/XnDeviceSensorV2/XnSensor.cpp index cdc4541..98bd71e 100644 --- a/Source/XnDeviceSensorV2/XnSensor.cpp +++ b/Source/XnDeviceSensorV2/XnSensor.cpp @@ -1,1355 +1,1335 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensor.h" - -#include "XnSensorDepthStream.h" -#include "XnSensorImageStream.h" -#include "XnSensorIRStream.h" -#include "XnSensorAudioStream.h" -#include "XnDeviceSensor.h" -#include "XnHostProtocol.h" -#include "XnDeviceSensorInit.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_SENSOR_MAX_STREAM_COUNT 5 -#define XN_SENSOR_FRAME_SYNC_MAX_DIFF 3 -#define XN_SENSOR_DEFAULT_CLOSE_STREAMS_ON_SHUTDOWN TRUE -#define XN_GLOBAL_CONFIG_FILE_NAME "GlobalDefaults.ini" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnWaitForSycnhedFrameData -{ - XnSensor* pThis; - const XnChar* strDepthStream; - const XnChar* strImageStream; -} XnWaitForSycnhedFrameData; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSensor::XnSensor() : - XnDeviceBase(XN_DEVICE_NAME, TRUE), - m_ErrorState(XN_MODULE_PROPERTY_ERROR_STATE, XN_STATUS_OK), - m_ResetSensorOnStartup(XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP, TRUE), - m_Interface(XN_MODULE_PROPERTY_USB_INTERFACE, XN_SENSOR_USB_INTERFACE_DEFAULT), - m_NumberOfBuffers(XN_MODULE_PROPERTY_NUMBER_OF_BUFFERS, 6), - m_ReadFromEP1(XN_MODULE_PROPERTY_READ_ENDPOINT_1, TRUE), - m_ReadFromEP2(XN_MODULE_PROPERTY_READ_ENDPOINT_2, TRUE), - m_ReadFromEP3(XN_MODULE_PROPERTY_READ_ENDPOINT_3, TRUE), - m_ReadData("ReadData", FALSE), - m_FrameSync(XN_MODULE_PROPERTY_FRAME_SYNC, FALSE), - m_FirmwareParam(XN_MODULE_PROPERTY_FIRMWARE_PARAM, NULL), - m_CmosBlankingUnits(XN_MODULE_PROPERTY_CMOS_BLANKING_UNITS, NULL), - m_CmosBlankingTime(XN_MODULE_PROPERTY_CMOS_BLANKING_TIME, NULL), - m_Reset(XN_MODULE_PROPERTY_RESET), - m_FirmwareMode(XN_MODULE_PROPERTY_FIRMWARE_MODE), - m_Version(XN_MODULE_PROPERTY_VERSION, &m_DevicePrivateData.Version, sizeof(m_DevicePrivateData.Version), NULL), - m_FixedParam(XN_MODULE_PROPERTY_FIXED_PARAMS, NULL), - m_CloseStreamsOnShutdown(XN_MODULE_PROPERTY_CLOSE_STREAMS_ON_SHUTDOWN, XN_SENSOR_DEFAULT_CLOSE_STREAMS_ON_SHUTDOWN), - m_ID(XN_MODULE_PROPERTY_ID), - m_pThis(this), - m_InstancePointer(XN_SENSOR_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL), - m_Firmware(&m_DevicePrivateData), - m_FixedParams(&m_Firmware, &m_DevicePrivateData), - m_SensorIO(&m_DevicePrivateData.SensorHandle), - m_FPS(), - m_CmosInfo(&m_Firmware, &m_DevicePrivateData), - m_Objects(&m_Firmware, &m_DevicePrivateData, &m_FixedParams, &m_FPS, &m_CmosInfo), - m_FrameSyncDump(XN_DUMP_CLOSED), - m_bInitialized(FALSE) -{ - // reset all data - xnOSMemSet(&m_DevicePrivateData, 0, sizeof(XnDevicePrivateData)); - m_strGlobalConfigFile[0] = '\0'; - - m_ResetSensorOnStartup.UpdateSetCallbackToDefault(); - m_Interface.UpdateSetCallback(SetInterfaceCallback, this); - m_NumberOfBuffers.UpdateSetCallback(SetNumberOfBuffersCallback, this); - m_ReadFromEP1.UpdateSetCallback(SetReadEndpoint1Callback, this); - m_ReadFromEP2.UpdateSetCallback(SetReadEndpoint2Callback, this); - m_ReadFromEP3.UpdateSetCallback(SetReadEndpoint3Callback, this); - m_ReadData.UpdateSetCallback(SetReadDataCallback, this); - m_FrameSync.UpdateSetCallbackToDefault(); - m_FirmwareParam.UpdateSetCallback(SetFirmwareParamCallback, this); - m_FirmwareParam.UpdateGetCallback(GetFirmwareParamCallback, this); - m_CmosBlankingUnits.UpdateSetCallback(SetCmosBlankingUnitsCallback, this); - m_CmosBlankingUnits.UpdateGetCallback(GetCmosBlankingUnitsCallback, this); - m_CmosBlankingTime.UpdateSetCallback(SetCmosBlankingTimeCallback, this); - m_CmosBlankingTime.UpdateGetCallback(GetCmosBlankingTimeCallback, this); - m_Reset.UpdateSetCallback(ResetCallback, this); - m_FirmwareMode.UpdateSetCallback(SetFirmwareModeCallback, this); - m_FirmwareMode.UpdateGetCallback(GetFirmwareModeCallback, this); - m_FixedParam.UpdateGetCallback(GetFixedParamsCallback, this); - m_CloseStreamsOnShutdown.UpdateSetCallbackToDefault(); - -} - -XnSensor::~XnSensor() -{ - XnSensor::Destroy(); -} - -XnStatus XnSensor::GetDefinition(XnDeviceDefinition* pDeviceDefinition) -{ - XN_VALIDATE_OUTPUT_PTR(pDeviceDefinition); - - pDeviceDefinition->cpName = XN_DEVICE_NAME; - pDeviceDefinition->cpDescription = XN_DEVICE_DESCRIPTION; - pDeviceDefinition->nMajorVersion = XN_DEVICE_MAJORVERSION; - pDeviceDefinition->nMinorVersion = XN_DEVICE_MINORVERSION; - pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - XnUInt32 nNumSensors = 0; - XnUInt32 nSensorIndex = 0; - XnChar cpBoardID[16]; - XnDevicePrivateData DevicePrivateData; - XnVersions Versions; - XnChar* pCurrConnectionString; - - XN_VALIDATE_INPUT_PTR(pnCount); - - xnOSMemSet(&DevicePrivateData, 0, sizeof(DevicePrivateData)); - - nRetVal = XnSensorIO::GetNumOfSensors(&nNumSensors); - XN_IS_STATUS_OK(nRetVal); - - XnUInt32 nArraySize = *pnCount; - - *pnCount = nNumSensors; - if (nArraySize < nNumSensors) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - // for now, the driver only supports telling if we have a sensor or not (and not how many), - // so result is always 0 or 1. - if (nNumSensors != 0) - { - XN_ASSERT(nNumSensors == 1); - strcpy(aConnectionStrings[0], "*:0"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::InitImpl(const XnDeviceConfig *pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Initializing device sensor..."); - - - // Frame Sync - XnCallbackHandle hCallbackDummy; - nRetVal = m_FrameSync.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetFirmware()->GetParams()->m_Stream0Mode.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetFirmware()->GetParams()->m_Stream1Mode.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - // other stuff - xnDumpInit(&m_FrameSyncDump, XN_DUMP_FRAME_SYNC, "HostTime(us),DepthNewData,DepthTimestamp(ms),ImageNewData,ImageTimestamp(ms),Diff(ms),Action\n", "FrameSync.csv"); - - nRetVal = XnDeviceBase::InitImpl(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - // now that everything is configured, open the sensor - nRetVal = InitSensor(pDeviceConfig); - if (nRetVal != XN_STATUS_OK) - { - Destroy(); - return (nRetVal); - } - - xnLogInfo(XN_MASK_DEVICE_SENSOR, "Device sensor initialized"); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::InitSensor(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - XnDevicePrivateData* pDevicePrivateData = GetDevicePrivateData(); - - pDevicePrivateData->pSensor = this; - - pDevicePrivateData->nDepthFramePos = 0; - pDevicePrivateData->nImageFramePos = 0; - xnOSMemCopy(&pDevicePrivateData->DeviceConfig, pDeviceConfig, sizeof(XnDeviceConfig)); - - xnOSMemSet(pDevicePrivateData->cpSensorID, 0, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); - - pDevicePrivateData->bSyncAudio = TRUE; - - switch (pDeviceConfig->DeviceMode) - { - case XN_DEVICE_MODE_READ: - break; - case XN_DEVICE_MODE_WRITE: - return (XN_STATUS_IO_DEVICE_MODE_NOT_SUPPORTED); - default: - return (XN_STATUS_IO_DEVICE_INVALID_MODE); - } - - // Register USB event callback - #if WIN32 - nRetVal = m_SensorIO.SetCallback(&USBEventCallback, this); - XN_IS_STATUS_OK(nRetVal); - #endif - - // open IO - nRetVal = m_SensorIO.OpenDevice(pDeviceConfig->cpConnectionString); - XN_IS_STATUS_OK(nRetVal); - - // initialize - nRetVal = XnDeviceSensorInit(pDevicePrivateData); - XN_IS_STATUS_OK(nRetVal); - - // init firmware - nRetVal = m_Firmware.Init((XnBool)m_ResetSensorOnStartup.GetValue()); - XN_IS_STATUS_OK(nRetVal); - m_bInitialized = TRUE; - - m_ResetSensorOnStartup.UpdateSetCallback(NULL, NULL); - - // Init modules - nRetVal = m_FixedParams.Init(); - XN_IS_STATUS_OK(nRetVal); - - // update serial number - nRetVal = m_ID.UnsafeUpdateValue(m_FixedParams.GetSensorSerial()); - XN_IS_STATUS_OK(nRetVal); - - AddSupportedStream(XN_STREAM_TYPE_DEPTH); - AddSupportedStream(XN_STREAM_TYPE_IMAGE); - AddSupportedStream(XN_STREAM_TYPE_IR); - AddSupportedStream(XN_STREAM_TYPE_AUDIO); - - return XN_STATUS_OK; -} - -XnStatus XnSensor::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - XnDevicePrivateData* pDevicePrivateData = GetDevicePrivateData(); - - - // if needed, close the streams - if (m_bInitialized && m_CloseStreamsOnShutdown.GetValue() == TRUE && m_ReadData.GetValue() == TRUE) - { - nRetVal = m_Firmware.GetParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); - nRetVal = m_Firmware.GetParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); - nRetVal = m_Firmware.GetParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); - } - - // close IO (including all reading threads) - m_SensorIO.CloseDevice(); - m_bInitialized = FALSE; - - - // close critical sections - if (pDevicePrivateData->hAudioBufferCriticalSection != NULL) - { - xnOSCloseCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); - pDevicePrivateData->hAudioBufferCriticalSection = NULL; - } - - if (pDevicePrivateData->hEndPointsCS != NULL) - { - xnOSCloseCriticalSection(&pDevicePrivateData->hEndPointsCS); - pDevicePrivateData->hEndPointsCS = NULL; - } - - // free buffers - XnDeviceSensorFreeBuffers(pDevicePrivateData); - - if (pDevicePrivateData->hExecuteMutex != NULL) - { - xnOSCloseMutex(&pDevicePrivateData->hExecuteMutex); - pDevicePrivateData->hExecuteMutex = NULL; - } - - XnDeviceBase::Destroy(); - - // close dumps - xnDumpClose(&pDevicePrivateData->TimestampsDump); - xnDumpClose(&pDevicePrivateData->BandwidthDump); - xnDumpClose(&pDevicePrivateData->MiniPacketsDump); - xnDumpClose(&m_FrameSyncDump); - - - m_Firmware.Free(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceBase::CreateDeviceModule(ppModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - // add sensor properties - XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); - XnProperty* pProps[] = - { - &m_ErrorState, &m_ResetSensorOnStartup, &m_Interface, &m_ReadFromEP1, - &m_ReadFromEP2, &m_ReadFromEP3, &m_ReadData, &m_NumberOfBuffers, &m_FirmwareParam, - &m_CmosBlankingUnits, &m_CmosBlankingTime, &m_Reset, &m_FirmwareMode, &m_Version, - &m_FixedParam, &m_FrameSync, &m_CloseStreamsOnShutdown, &m_InstancePointer, &m_ID, - }; - - nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(*ppModuleHolder); - *ppModuleHolder = NULL; - return (nRetVal); - } - - // configure it from global file - if (m_strGlobalConfigFile[0] != '\0') - { - nRetVal = pModule->LoadConfigFromFile(m_strGlobalConfigFile); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceBase::CreateStreamImpl(strType, strName, pInitialSet); - XN_IS_STATUS_OK(nRetVal); - - // and configure it from global config file - nRetVal = ConfigureModuleFromGlobalFile(strName, strType); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // make sure reading from streams is turned on - if (!m_ReadData.GetValue()) - { - nRetVal = m_ReadData.SetValue(TRUE); - XN_IS_STATUS_OK(nRetVal); - } - - XnDeviceStream* pStream; - XnSensorStreamHelper* pHelper; - - // create stream - if (strcmp(StreamType, XN_STREAM_TYPE_DEPTH) == 0) - { - XnSensorDepthStream* pDepthStream; - XN_VALIDATE_NEW(pDepthStream, XnSensorDepthStream, StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); - pStream = pDepthStream; - pHelper = pDepthStream->GetHelper(); - } - else if (strcmp(StreamType, XN_STREAM_TYPE_IMAGE) == 0) - { - XnSensorImageStream* pImageStream; - XN_VALIDATE_NEW(pImageStream, XnSensorImageStream, StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); - pStream = pImageStream; - pHelper = pImageStream->GetHelper(); - } - else if (strcmp(StreamType, XN_STREAM_TYPE_IR) == 0) - { - XnSensorIRStream* pIRStream; - XN_VALIDATE_NEW(pIRStream, XnSensorIRStream, StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); - pStream = pIRStream; - pHelper = pIRStream->GetHelper(); - } - else if (strcmp(StreamType, XN_STREAM_TYPE_AUDIO) == 0) - { - XnSensorAudioStream* pAudioStream; - XN_VALIDATE_NEW(pAudioStream, XnSensorAudioStream, StreamName, &m_Objects); - pStream = pAudioStream; - pHelper = pAudioStream->GetHelper(); - } - else - { - XN_LOG_WARNING_RETURN(XN_STATUS_UNSUPPORTED_STREAM, XN_MASK_DEVICE_SENSOR, "Unsupported stream type: %s", StreamType); - } - - *ppStreamHolder = XN_NEW(XnSensorStreamHolder, pStream, pHelper); - - return (XN_STATUS_OK); -} - -void XnSensor::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) -{ - XN_DELETE(pStreamHolder->GetModule()); - XN_DELETE(pStreamHolder); -} - -XnStatus XnSensor::OpenAllStreams() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Opening all streams..."); - - // take a list of all the streams - const XnChar* astrStreams[XN_SENSOR_MAX_STREAM_COUNT]; - XnUInt32 nStreamCount = XN_SENSOR_MAX_STREAM_COUNT; - XnDeviceStream* apStreams[XN_SENSOR_MAX_STREAM_COUNT]; - XnSensorStreamHolder* apSensorStreams[XN_SENSOR_MAX_STREAM_COUNT]; - - nRetVal = GetStreamNames(astrStreams, &nStreamCount); - XN_IS_STATUS_OK(nRetVal); - - for (XnUInt32 i = 0; i < nStreamCount; ++i) - { - XnDeviceModuleHolder* pHolder; - nRetVal = FindStream(astrStreams[i], &pHolder); - XN_IS_STATUS_OK(nRetVal); - - apSensorStreams[i] = (XnSensorStreamHolder*)(pHolder); - apStreams[i] = apSensorStreams[i]->GetStream(); - } - - // NOTE: the following is an ugly patch. When depth and IR both exist, Depth stream MUST be configured - // and opened BEFORE IR stream. So, generally, if one of the streams is depth, we move it to be first. - for (XnUInt32 i = 1; i < nStreamCount; ++i) - { - if (strcmp(apStreams[i]->GetType(), XN_STREAM_TYPE_DEPTH) == 0) - { - // switch it with the one in location 0 - const XnChar* strTempName = astrStreams[0]; - XnDeviceStream* pTempStream = apStreams[0]; - XnSensorStreamHolder* pTempHolder = apSensorStreams[0]; - - astrStreams[0] = astrStreams[i]; - apStreams[0] = apStreams[i]; - apSensorStreams[0] = apSensorStreams[i]; - - astrStreams[i] = strTempName; - apStreams[i] = pTempStream; - apSensorStreams[i] = pTempHolder; - break; - } - } - - // now configure them all - for (XnUInt32 i = 0; i < nStreamCount; ++i) - { - if (!apStreams[i]->IsOpen()) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Configuring stream %s...", apStreams[i]->GetName()); - nRetVal = apSensorStreams[i]->Configure(); - XN_IS_STATUS_OK(nRetVal); - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s is configured", apStreams[i]->GetName()); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s is already open.", apStreams[i]->GetName()); - } - } - - // and open them all - for (XnUInt32 i = 0; i < nStreamCount; ++i) - { - if (!apStreams[i]->IsOpen()) - { - nRetVal = apSensorStreams[i]->FinalOpen(); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::ReadStream(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check internal state - nRetVal = CheckIfReadingAllowed(); - XN_IS_STATUS_OK(nRetVal); - - // call base - nRetVal = XnDeviceBase::ReadStream(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::GetSharedBufferPool(const XnChar* strStream, XnSharedMemoryBufferPool** ppBufferPool) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModuleHolder* pHolder; - nRetVal = FindStream(strStream, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHolder* pSensorStreamHolder = (XnSensorStreamHolder*)(pHolder); - *ppBufferPool = pSensorStreamHolder->GetSharedBufferPool(); - - return (XN_STATUS_OK); -} - -XnBool XnSensor::HasSynchedFrameArrived(const XnChar* strDepthStream, const XnChar* strImageStream) -{ - // find both streams - XnDeviceStream* pDepth; - XnDeviceStream* pImage; - - if (XN_STATUS_OK != FindStream(strDepthStream, &pDepth)) - return FALSE; - - if (XN_STATUS_OK != FindStream(strImageStream, &pImage)) - return FALSE; - - XnUInt32 nThreshold = XN_SENSOR_FRAME_SYNC_MAX_DIFF; - if (IsHighResTimestamps()) - nThreshold *= 1000; - - // wait for both to advance, and time difference to be less than threshold - XnInt32 nTimestampDiff = XnInt32(pDepth->GetLastTimestamp() - pImage->GetLastTimestamp()); - - XnBool bConditionMet = ( - pDepth->IsNewDataAvailable() && - pImage->IsNewDataAvailable() && - (XnUInt32)abs(nTimestampDiff) <= nThreshold - ); - - if (xnLogIsDumpMaskEnabled(XN_DUMP_FRAME_SYNC)) - { - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - xnDumpWriteString(m_FrameSyncDump, "%llu,%u,%llu,%u,%llu,%s\n", - nNow, - pDepth->IsNewDataAvailable(), - pDepth->GetLastTimestamp(), - pImage->IsNewDataAvailable(), - pImage->GetLastTimestamp(), - bConditionMet ? "OK" : "Waiting"); - } - - return bConditionMet; -} - -XnBool XnSensor::HasSynchedFrameArrived(void* pCookie) -{ - XnWaitForSycnhedFrameData* pData = (XnWaitForSycnhedFrameData*)pCookie; - return pData->pThis->HasSynchedFrameArrived(pData->strDepthStream, pData->strImageStream); -} - -XnStatus XnSensor::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_FrameSync.GetValue() == TRUE) - { - // FrameSync is on. check if we have both the image and the depth stream - XnStreamData* apStreamData[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; - XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; - - nRetVal = XnStreamDataSetCopyToArray(pSet, apStreamData, &nCount); - XN_IS_STATUS_OK(nRetVal); - - const XnChar* strImageName = NULL; - const XnChar* strDepthName = NULL; - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - - for (XnUInt32 i = 0; i < nCount; ++i) - { - nRetVal = GetProperty(apStreamData[i]->StreamName, XN_STREAM_PROPERTY_TYPE, strType); - XN_IS_STATUS_OK(nRetVal); - - if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) - { - strDepthName = apStreamData[i]->StreamName; - } - else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) - { - strImageName = apStreamData[i]->StreamName; - } - - // if both are present, wait for frame sync - if (strImageName != NULL && strDepthName != NULL) - { - XnWaitForSycnhedFrameData WaitData; - WaitData.pThis = this; - WaitData.strDepthStream = strDepthName; - WaitData.strImageStream = strImageName; - - nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnSensor::HasSynchedFrameArrived, &WaitData); - if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) - { - xnLogError(XN_MASK_DDK, "Not responding - Didn't get any synced frame"); - return (XN_STATUS_DEVICE_FRAMES_NOT_SYNCHED); - } - else - { - XN_IS_STATUS_OK(nRetVal); - } - } - } // for loop - } - - // if we reached here, either frame sync is off, or one of the streams is not read from. - // either way, we should just wait for the primary stream. - nRetVal = XnDeviceBase::WaitForPrimaryStream(hNewDataEvent, pSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::Read(XnStreamDataSet* pStreamOutputSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check internal state - nRetVal = CheckIfReadingAllowed(); - XN_IS_STATUS_OK(nRetVal); - - // call base - nRetVal = XnDeviceBase::Read(pStreamOutputSet); - XN_IS_STATUS_OK(nRetVal); - - m_FPS.MarkReadCalled(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::WriteStream(const XnStreamData* pStreamOutput) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnSensor::Write(const XnStreamDataSet* pStreamOutputSet) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnSensor::Seek(XnUInt64 nTimestamp) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnSensor::SeekFrame(XnUInt32 nFrameID) -{ - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); -} - -XnStatus XnSensor::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(csINIFilePath); - XN_VALIDATE_INPUT_PTR(csSectionName); - - // we first need to configure the USB interface (we want to do so BEFORE creating streams) - nRetVal = m_Interface.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_NumberOfBuffers.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_ReadFromEP1.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_ReadFromEP2.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_ReadFromEP3.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - // now create all streams - nRetVal = CreateStreamsFromFile(csINIFilePath, csSectionName); - XN_IS_STATUS_OK(nRetVal); - - // now configure DEVICE module (primary stream, global mirror, etc.) - nRetVal = DeviceModule()->LoadConfigFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - // and now configure the streams - XnDeviceModuleHolderList streams; - nRetVal = GetStreamsList(streams); - XN_IS_STATUS_OK(nRetVal); - - for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) - { - XnDeviceModuleHolder* pHolder = *it; - nRetVal = pHolder->GetModule()->LoadConfigFromFile(csINIFilePath); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::CheckIfReadingAllowed() -{ - return GetErrorState(); -} - -XnStatus XnSensor::InitReading() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // open data endpoints - nRetVal = m_SensorIO.OpenDataEndPoints((XnSensorUsbInterface)m_Interface.GetValue()); - XN_IS_STATUS_OK(nRetVal); - - // take frequency information - XnFrequencyInformation FrequencyInformation; - - nRetVal = XnHostProtocolAlgorithmParams(&m_DevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_FREQUENCY, &FrequencyInformation, sizeof(XnFrequencyInformation), (XnResolutions)0, 0); - if (nRetVal != XN_STATUS_OK) - return nRetVal; - - m_DevicePrivateData.fDeviceFrequency = XN_PREPARE_VAR_FLOAT_IN_BUFFER(FrequencyInformation.fDeviceFrequency); - - // Init Dumps - m_DevicePrivateData.BandwidthDump = XN_DUMP_CLOSED; - xnDumpInit(&m_DevicePrivateData.BandwidthDump, XN_DUMP_BANDWIDTH, "Timestamp,Frame Type,Frame ID,Size\n", "Bandwidth.csv"); - m_DevicePrivateData.TimestampsDump = XN_DUMP_CLOSED; - xnDumpInit(&m_DevicePrivateData.TimestampsDump, XN_DUMP_TIMESTAMPS, "Host Time (us),Stream,Device TS,Time (ms),Comments\n", "Timestamps.csv"); - m_DevicePrivateData.MiniPacketsDump = XN_DUMP_CLOSED; - xnDumpInit(&m_DevicePrivateData.MiniPacketsDump, XN_DUMP_MINI_PACKETS, "HostTS,Type,ID,Size,Timestamp\n", "MiniPackets.csv"); - - m_DevicePrivateData.nGlobalReferenceTS = 0; - nRetVal = xnOSCreateCriticalSection(&m_DevicePrivateData.hEndPointsCS); - XN_IS_STATUS_OK(nRetVal); - - // NOTE: when we go up, some streams might be open, and so we'll receive lots of garbage. - // wait till streams are turned off, and then start reading. -// pDevicePrivateData->bIgnoreDataPackets = TRUE; - - // open input threads - nRetVal = XnDeviceSensorOpenInputThreads(GetDevicePrivateData(), (XnBool)m_ReadFromEP1.GetValue(), (XnBool)m_ReadFromEP2.GetValue(), (XnBool)m_ReadFromEP3.GetValue()); - XN_IS_STATUS_OK(nRetVal); - - - return XN_STATUS_OK; -} - - -XnStatus XnSensor::ParseConnectionString(const XnChar* csConnectionString, XnChar* csSensorID, XnUInt32* pnBoardID) -{ - XnStatus nRetVal = XN_STATUS_OK; - -/* const XnChar* cpSepPos = strstr(csConnectionString, XN_DEVICE_SENSOR_BOARDID_SEP); - if (cpSepPos == NULL) - { - return (XN_STATUS_IO_INVALID_CONNECTION_STRING); - } - - XnUInt32 nSepPos = cpSepPos - csConnectionString; - - xnOSMemSet(csSensorID, 0, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); - - nRetVal = xnOSStrNCopy(csSensorID, csConnectionString, nSepPos, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); - XN_IS_STATUS_OK(nRetVal); - - *pnBoardID = atoi(cpSepPos + 1); -*/ - return (XN_STATUS_OK); -} - -XnStatus XnSensor::ValidateSensorID(XnChar* csSensorID) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (strcmp(csSensorID, XN_DEVICE_SENSOR_DEFAULT_ID) != 0) - { - if (strcmp(csSensorID, GetFixedParams()->GetSensorSerial()) != 0) - { - return (XN_STATUS_IO_DEVICE_WRONG_SERIAL); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::ResolveGlobalConfigFileName(XnChar* strConfigFile, XnUInt32 nBufSize, const XnChar* strConfigDir) -{ - XnUInt32 nWritten = 0; - return xnOSStrFormat(strConfigFile, nBufSize, &nWritten, "%s%s%s", strConfigDir, XN_FILE_DIR_SEP, XN_GLOBAL_CONFIG_FILE_NAME); -} - -XnStatus XnSensor::SetGlobalConfigFile(const XnChar* strConfigFile) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSStrCopy(m_strGlobalConfigFile, strConfigFile, XN_FILE_MAX_PATH); - XN_IS_STATUS_OK(nRetVal); - - XnBool bExists; - nRetVal = xnOSDoesFileExist(m_strGlobalConfigFile, &bExists); - XN_IS_STATUS_OK(nRetVal); - - if (!bExists) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Global configuration file '%s' was not found.", m_strGlobalConfigFile); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::ConfigureModuleFromGlobalFile(const XnChar* strModule, const XnChar* strSection /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceModule* pModule; - nRetVal = FindModule(strModule, &pModule); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pModule->LoadConfigFromFile(m_strGlobalConfigFile, strSection); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::GetFirmwareParam(XnInnerParamData* pParam) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnHostProtocolGetParam(&m_DevicePrivateData, pParam->nParam, pParam->nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::GetCmosBlankingUnits(XnCmosBlankingUnits* pBlanking) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) - { - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); - } - - nRetVal = XnHostProtocolGetCmosBlanking(&m_DevicePrivateData, pBlanking->nCmosID, &pBlanking->nUnits); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::GetCmosBlankingTime(XnCmosBlankingTime* pBlanking) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check version - if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) - { - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); - } - - // get value in units - XnCmosBlankingUnits blankingUnits; - blankingUnits.nCmosID = pBlanking->nCmosID; - nRetVal = GetCmosBlankingUnits(&blankingUnits); - XN_IS_STATUS_OK(nRetVal); - - // get coefficients - const XnCmosBlankingCoefficients* pCoeffs = m_CmosInfo.GetBlankingCoefficients(pBlanking->nCmosID); - - // translate to time - pBlanking->nTimeInMilliseconds = (pCoeffs->fA * blankingUnits.nUnits + pCoeffs->fB)/1000; - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::GetFirmwareMode(XnParamCurrentMode* pnMode) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_Firmware.GetInfo()->nFWVer == XN_SENSOR_FW_VER_0_17) - { - *pnMode = m_Firmware.GetInfo()->nCurrMode; - } - else - { - XnUInt16 nMode; - nRetVal = XnHostProtocolGetMode(&m_DevicePrivateData, nMode); - XN_IS_STATUS_OK(nRetVal); - - switch (nMode) - { - case XN_HOST_PROTOCOL_MODE_PS: - *pnMode = XN_MODE_PS; - break; - case XN_HOST_PROTOCOL_MODE_MAINTENANCE: - *pnMode = XN_MODE_MAINTENANCE; - break; - case XN_HOST_PROTOCOL_MODE_SAFE_MODE: - *pnMode = XN_MODE_SAFE_MODE; - break; - default: - printf("Got Unknown Firmware Mode %d\n", nMode); - return XN_STATUS_DEVICE_BAD_PARAM; - } - } - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::GetFixedParams(XnDynamicSizeBuffer* pBuffer) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (pBuffer->nMaxSize < sizeof(XnFixedParams)) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - XnFixedParams fixed; - nRetVal = XnHostProtocolGetFixedParams(GetDevicePrivateData(), fixed); - XN_IS_STATUS_OK(nRetVal); - - xnOSMemCopy(pBuffer->pData, &fixed, sizeof(XnFixedParams)); - pBuffer->nDataSize = sizeof(XnFixedParams); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::SetErrorState(XnStatus errorState) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (errorState != GetErrorState()) - { - if (errorState == XN_STATUS_OK) - { - xnLogInfo(XN_MASK_DEVICE_SENSOR, "Device is back to normal state."); - } - else - { - xnLogError(XN_MASK_DEVICE_SENSOR, "Device has entered error mode: %s", xnGetStatusString(errorState)); - } - - nRetVal = m_ErrorState.UnsafeUpdateValue((XnUInt64)errorState); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetInterface(XnSensorUsbInterface nInterface) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // we don't allow change if requested value is specific and different than current - if (m_ReadData.GetValue() == TRUE && - nInterface != XN_SENSOR_USB_INTERFACE_DEFAULT && - nInterface != m_SensorIO.GetCurrentInterface()) - { - return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); - } - - nRetVal = m_Interface.UnsafeUpdateValue(nInterface); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetNumberOfBuffers(XnUInt32 nCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // This is a special func. It can only be changed BEFORE reading starts - if (m_ReadData.GetValue() == FALSE) - { - nRetVal = m_NumberOfBuffers.UnsafeUpdateValue(nCount); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // check it's the same value - if (nCount != m_NumberOfBuffers.GetValue()) - { - return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetReadEndpoint1(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // This is a special func. It can only be changed BEFORE reading starts - if (m_ReadData.GetValue() == FALSE) - { - nRetVal = m_ReadFromEP1.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // check it's the same value - if (bRead != m_ReadFromEP1.GetValue()) - { - return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetReadEndpoint2(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // This is a special func. It can only be changed BEFORE reading starts - if (m_ReadData.GetValue() == FALSE) - { - nRetVal = m_ReadFromEP2.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // check it's the same value - if (bRead != m_ReadFromEP2.GetValue()) - { - return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetReadEndpoint3(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // This is a special func. It can only be changed BEFORE reading starts - if (m_ReadData.GetValue() == FALSE) - { - nRetVal = m_ReadFromEP3.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // check it's the same value - if (bRead != m_ReadFromEP3.GetValue()) - { - return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetReadData(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!bRead) - { - return XN_STATUS_ERROR; - } - else - { - nRetVal = InitReading(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_ReadData.UnsafeUpdateValue(TRUE); - XN_IS_STATUS_OK(nRetVal); - - // no longer needed - m_ReadData.UpdateSetCallback(NULL, NULL); - } - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::SetFirmwareParam(const XnInnerParamData* pParam) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnHostProtocolSetParam(&m_DevicePrivateData, pParam->nParam, pParam->nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::SetCmosBlankingUnits(const XnCmosBlankingUnits* pBlanking) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) - { - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); - } - - nRetVal = XnHostProtocolSetCmosBlanking(&m_DevicePrivateData, pBlanking->nUnits, pBlanking->nCmosID, pBlanking->nNumberOfFrames); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetCmosBlankingTime(const XnCmosBlankingTime* pBlanking) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check version - if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) - { - return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); - } - - // get coefficients - const XnCmosBlankingCoefficients* pCoeffs = m_CmosInfo.GetBlankingCoefficients(pBlanking->nCmosID); - - // translate to units request - XnCmosBlankingUnits blankingUnits; - blankingUnits.nCmosID = pBlanking->nCmosID; - blankingUnits.nNumberOfFrames = pBlanking->nNumberOfFrames; - blankingUnits.nUnits = XnUInt16((pBlanking->nTimeInMilliseconds*1000 - pCoeffs->fB)/pCoeffs->fA); - - nRetVal = SetCmosBlankingUnits(&blankingUnits); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::Reset(XnParamResetType nType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnHostProtocolReset(&m_DevicePrivateData, nType); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensor::SetFirmwareMode(XnParamCurrentMode nMode) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_Firmware.GetInfo()->nFWVer == XN_SENSOR_FW_VER_0_17) - { - m_Firmware.GetInfo()->nCurrMode = nMode; - return (XN_STATUS_OK); - } - - XnHostProtocolModeType nActualValue; - - switch (nMode) - { - case XN_MODE_PS: - nActualValue = XN_HOST_PROTOCOL_MODE_PS; - break; - case XN_MODE_MAINTENANCE: - nActualValue = XN_HOST_PROTOCOL_MODE_MAINTENANCE; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - nRetVal = XnHostProtocolSetMode(&m_DevicePrivateData, nActualValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensor::OnFrameSyncPropertyChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_ReadData.GetValue() == TRUE) - { - // decide firmware frame sync - both streams are on, and user asked for it - XnBool bFrameSync = ( - m_FrameSync.GetValue() == TRUE && - GetFirmware()->GetParams()->m_Stream0Mode.GetValue() == XN_VIDEO_STREAM_COLOR && - GetFirmware()->GetParams()->m_Stream1Mode.GetValue() == XN_VIDEO_STREAM_DEPTH - ); - - nRetVal = GetFirmware()->GetParams()->m_FrameSyncEnabled.SetValue(bFrameSync); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetInterfaceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->XnSensor::SetInterface((XnSensorUsbInterface)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetNumberOfBuffersCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->SetNumberOfBuffers((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint1Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->XnSensor::SetReadEndpoint1((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint2Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->XnSensor::SetReadEndpoint2((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint3Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->XnSensor::SetReadEndpoint3((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetReadDataCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->XnSensor::SetReadData((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetFirmwareParamCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnInnerParamData); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->SetFirmwareParam((const XnInnerParamData*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetCmosBlankingUnitsCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingUnits); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->SetCmosBlankingUnits((const XnCmosBlankingUnits*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetCmosBlankingTimeCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingTime); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->SetCmosBlankingTime((const XnCmosBlankingTime*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::ResetCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->Reset((XnParamResetType)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::SetFirmwareModeCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->SetFirmwareMode((XnParamCurrentMode)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::GetFirmwareParamCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnInnerParamData); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->GetFirmwareParam((XnInnerParamData*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::GetCmosBlankingUnitsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingUnits); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->GetCmosBlankingUnits((XnCmosBlankingUnits*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::GetCmosBlankingTimeCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingTime); - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->GetCmosBlankingTime((XnCmosBlankingTime*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::GetFirmwareModeCallback(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - XnParamCurrentMode nMode; - XnStatus nRetVal = pThis->GetFirmwareMode(&nMode); - XN_IS_STATUS_OK(nRetVal); - - *pnValue = nMode; - return XN_STATUS_OK; -} - -XnStatus XN_CALLBACK_TYPE XnSensor::FrameSyncPropertyChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnSensor* pThis = (XnSensor*)pCookie; - return pThis->OnFrameSyncPropertyChanged(); -} - -XnStatus XN_CALLBACK_TYPE XnSensor::GetFixedParamsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnDynamicSizeBuffer); - XnSensor* pThis = (XnSensor*)pCookie; - XnDynamicSizeBuffer* pBuffer = (XnDynamicSizeBuffer*)gbValue.pData; - return pThis->GetFixedParams(pBuffer); -} - -XnBool XN_CALLBACK_TYPE XnSensor::USBEventCallback(XnUSBEventType USBEventType, XnChar* cpDevPath, void* pCallbackData) -{ - XnSensor* pXnSensor = (XnSensor*)pCallbackData; - if (USBEventType == XN_USB_EVENT_DEVICE_DISCONNECT) - { - pXnSensor->SetErrorState(XN_STATUS_DEVICE_NOT_CONNECTED); - } - /*else - { - pXnSensor->SetErrorState(XN_STATUS_OK); - }*/ - //TODO: Uncomment this once we can deal with re-connections - - return TRUE; -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensor.h" + +#include "XnSensorDepthStream.h" +#include "XnSensorImageStream.h" +#include "XnSensorIRStream.h" +#include "XnSensorAudioStream.h" +#include "XnDeviceSensor.h" +#include "XnHostProtocol.h" +#include "XnDeviceSensorInit.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_MAX_STREAM_COUNT 5 +#define XN_SENSOR_FRAME_SYNC_MAX_DIFF 3 +#define XN_SENSOR_DEFAULT_CLOSE_STREAMS_ON_SHUTDOWN TRUE +#define XN_GLOBAL_CONFIG_FILE_NAME "GlobalDefaults.ini" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +typedef struct XnWaitForSycnhedFrameData +{ + XnSensor* pThis; + const XnChar* strDepthStream; + const XnChar* strImageStream; +} XnWaitForSycnhedFrameData; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensor::XnSensor() : + XnDeviceBase(XN_DEVICE_NAME, TRUE), + m_ErrorState(XN_MODULE_PROPERTY_ERROR_STATE, XN_STATUS_OK), + m_ResetSensorOnStartup(XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP, TRUE), + m_Interface(XN_MODULE_PROPERTY_USB_INTERFACE, XN_SENSOR_USB_INTERFACE_DEFAULT), + m_NumberOfBuffers(XN_MODULE_PROPERTY_NUMBER_OF_BUFFERS, 6), + m_ReadFromEP1(XN_MODULE_PROPERTY_READ_ENDPOINT_1, TRUE), + m_ReadFromEP2(XN_MODULE_PROPERTY_READ_ENDPOINT_2, TRUE), + m_ReadFromEP3(XN_MODULE_PROPERTY_READ_ENDPOINT_3, TRUE), + m_ReadData("ReadData", FALSE), + m_FrameSync(XN_MODULE_PROPERTY_FRAME_SYNC, FALSE), + m_FirmwareParam(XN_MODULE_PROPERTY_FIRMWARE_PARAM, NULL), + m_CmosBlankingUnits(XN_MODULE_PROPERTY_CMOS_BLANKING_UNITS, NULL), + m_CmosBlankingTime(XN_MODULE_PROPERTY_CMOS_BLANKING_TIME, NULL), + m_Reset(XN_MODULE_PROPERTY_RESET), + m_FirmwareMode(XN_MODULE_PROPERTY_FIRMWARE_MODE), + m_Version(XN_MODULE_PROPERTY_VERSION, &m_DevicePrivateData.Version, sizeof(m_DevicePrivateData.Version), NULL), + m_FixedParam(XN_MODULE_PROPERTY_FIXED_PARAMS, NULL), + m_CloseStreamsOnShutdown(XN_MODULE_PROPERTY_CLOSE_STREAMS_ON_SHUTDOWN, XN_SENSOR_DEFAULT_CLOSE_STREAMS_ON_SHUTDOWN), + m_ID(XN_MODULE_PROPERTY_ID), + m_pThis(this), + m_InstancePointer(XN_SENSOR_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL), + m_USBPath(XN_MODULE_PROPERTY_USB_PATH), + m_Firmware(&m_DevicePrivateData), + m_FixedParams(&m_Firmware, &m_DevicePrivateData), + m_SensorIO(&m_DevicePrivateData.SensorHandle), + m_FPS(), + m_CmosInfo(&m_Firmware, &m_DevicePrivateData), + m_Objects(&m_Firmware, &m_DevicePrivateData, &m_FixedParams, &m_FPS, &m_CmosInfo), + m_FrameSyncDump(XN_DUMP_CLOSED), + m_bInitialized(FALSE) +{ + // reset all data + xnOSMemSet(&m_DevicePrivateData, 0, sizeof(XnDevicePrivateData)); + m_strGlobalConfigFile[0] = '\0'; + + m_ResetSensorOnStartup.UpdateSetCallbackToDefault(); + m_Interface.UpdateSetCallback(SetInterfaceCallback, this); + m_NumberOfBuffers.UpdateSetCallback(SetNumberOfBuffersCallback, this); + m_ReadFromEP1.UpdateSetCallback(SetReadEndpoint1Callback, this); + m_ReadFromEP2.UpdateSetCallback(SetReadEndpoint2Callback, this); + m_ReadFromEP3.UpdateSetCallback(SetReadEndpoint3Callback, this); + m_ReadData.UpdateSetCallback(SetReadDataCallback, this); + m_FrameSync.UpdateSetCallbackToDefault(); + m_FirmwareParam.UpdateSetCallback(SetFirmwareParamCallback, this); + m_FirmwareParam.UpdateGetCallback(GetFirmwareParamCallback, this); + m_CmosBlankingUnits.UpdateSetCallback(SetCmosBlankingUnitsCallback, this); + m_CmosBlankingUnits.UpdateGetCallback(GetCmosBlankingUnitsCallback, this); + m_CmosBlankingTime.UpdateSetCallback(SetCmosBlankingTimeCallback, this); + m_CmosBlankingTime.UpdateGetCallback(GetCmosBlankingTimeCallback, this); + m_Reset.UpdateSetCallback(ResetCallback, this); + m_FirmwareMode.UpdateSetCallback(SetFirmwareModeCallback, this); + m_FirmwareMode.UpdateGetCallback(GetFirmwareModeCallback, this); + m_FixedParam.UpdateGetCallback(GetFixedParamsCallback, this); + m_CloseStreamsOnShutdown.UpdateSetCallbackToDefault(); + +} + +XnSensor::~XnSensor() +{ + XnSensor::Destroy(); +} + +XnStatus XnSensor::GetDefinition(XnDeviceDefinition* pDeviceDefinition) +{ + XN_VALIDATE_OUTPUT_PTR(pDeviceDefinition); + + pDeviceDefinition->cpName = XN_DEVICE_NAME; + pDeviceDefinition->cpDescription = XN_DEVICE_DESCRIPTION; + pDeviceDefinition->nMajorVersion = XN_DEVICE_MAJORVERSION; + pDeviceDefinition->nMinorVersion = XN_DEVICE_MINORVERSION; + pDeviceDefinition->nXironVersion = XN_PS_MAJOR_VERSION; + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + XN_VALIDATE_INPUT_PTR(pnCount); + + nRetVal = XnSensorIO::EnumerateSensors(aConnectionStrings, pnCount); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::InitImpl(const XnDeviceConfig *pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Initializing device sensor..."); + + + // Frame Sync + XnCallbackHandle hCallbackDummy; + nRetVal = m_FrameSync.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetFirmware()->GetParams()->m_Stream0Mode.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetFirmware()->GetParams()->m_Stream1Mode.OnChangeEvent().Register(FrameSyncPropertyChangedCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + // other stuff + xnDumpInit(&m_FrameSyncDump, XN_DUMP_FRAME_SYNC, "HostTime(us),DepthNewData,DepthTimestamp(ms),ImageNewData,ImageTimestamp(ms),Diff(ms),Action\n", "FrameSync.csv"); + + nRetVal = XnDeviceBase::InitImpl(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + // now that everything is configured, open the sensor + nRetVal = InitSensor(pDeviceConfig); + if (nRetVal != XN_STATUS_OK) + { + Destroy(); + return (nRetVal); + } + + xnLogInfo(XN_MASK_DEVICE_SENSOR, "Device sensor initialized"); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::InitSensor(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + XnDevicePrivateData* pDevicePrivateData = GetDevicePrivateData(); + + pDevicePrivateData->pSensor = this; + + pDevicePrivateData->nDepthFramePos = 0; + pDevicePrivateData->nImageFramePos = 0; + xnOSMemCopy(&pDevicePrivateData->DeviceConfig, pDeviceConfig, sizeof(XnDeviceConfig)); + + xnOSMemSet(pDevicePrivateData->cpSensorID, 0, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); + + pDevicePrivateData->bSyncAudio = TRUE; + + switch (pDeviceConfig->DeviceMode) + { + case XN_DEVICE_MODE_READ: + break; + case XN_DEVICE_MODE_WRITE: + return (XN_STATUS_IO_DEVICE_MODE_NOT_SUPPORTED); + default: + return (XN_STATUS_IO_DEVICE_INVALID_MODE); + } + + // Register USB event callback + #if WIN32 + nRetVal = m_SensorIO.SetCallback(&USBEventCallback, this); + XN_IS_STATUS_OK(nRetVal); + #endif + + // open IO + nRetVal = m_SensorIO.OpenDevice(pDeviceConfig->cpConnectionString); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_USBPath.UnsafeUpdateValue(m_SensorIO.GetDevicePath()); + XN_IS_STATUS_OK(nRetVal); + + // initialize + nRetVal = XnDeviceSensorInit(pDevicePrivateData); + XN_IS_STATUS_OK(nRetVal); + + // init firmware + nRetVal = m_Firmware.Init((XnBool)m_ResetSensorOnStartup.GetValue()); + XN_IS_STATUS_OK(nRetVal); + m_bInitialized = TRUE; + + m_ResetSensorOnStartup.UpdateSetCallback(NULL, NULL); + + // Init modules + nRetVal = m_FixedParams.Init(); + XN_IS_STATUS_OK(nRetVal); + + // update serial number + nRetVal = m_ID.UnsafeUpdateValue(m_FixedParams.GetSensorSerial()); + XN_IS_STATUS_OK(nRetVal); + + AddSupportedStream(XN_STREAM_TYPE_DEPTH); + AddSupportedStream(XN_STREAM_TYPE_IMAGE); + AddSupportedStream(XN_STREAM_TYPE_IR); + AddSupportedStream(XN_STREAM_TYPE_AUDIO); + + return XN_STATUS_OK; +} + +XnStatus XnSensor::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + XnDevicePrivateData* pDevicePrivateData = GetDevicePrivateData(); + + + // if needed, close the streams + if (m_bInitialized && m_CloseStreamsOnShutdown.GetValue() == TRUE && m_ReadData.GetValue() == TRUE) + { + nRetVal = m_Firmware.GetParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); + nRetVal = m_Firmware.GetParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); + nRetVal = m_Firmware.GetParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); + } + + // close IO (including all reading threads) + m_SensorIO.CloseDevice(); + m_bInitialized = FALSE; + + + // close critical sections + if (pDevicePrivateData->hAudioBufferCriticalSection != NULL) + { + xnOSCloseCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); + pDevicePrivateData->hAudioBufferCriticalSection = NULL; + } + + if (pDevicePrivateData->hEndPointsCS != NULL) + { + xnOSCloseCriticalSection(&pDevicePrivateData->hEndPointsCS); + pDevicePrivateData->hEndPointsCS = NULL; + } + + // free buffers + XnDeviceSensorFreeBuffers(pDevicePrivateData); + + if (pDevicePrivateData->hExecuteMutex != NULL) + { + xnOSCloseMutex(&pDevicePrivateData->hExecuteMutex); + pDevicePrivateData->hExecuteMutex = NULL; + } + + XnDeviceBase::Destroy(); + + // close dumps + xnDumpClose(&pDevicePrivateData->TimestampsDump); + xnDumpClose(&pDevicePrivateData->BandwidthDump); + xnDumpClose(&pDevicePrivateData->MiniPacketsDump); + xnDumpClose(&m_FrameSyncDump); + + + m_Firmware.Free(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceBase::CreateDeviceModule(ppModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + // add sensor properties + XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); + XnProperty* pProps[] = + { + &m_ErrorState, &m_ResetSensorOnStartup, &m_Interface, &m_ReadFromEP1, + &m_ReadFromEP2, &m_ReadFromEP3, &m_ReadData, &m_NumberOfBuffers, &m_FirmwareParam, + &m_CmosBlankingUnits, &m_CmosBlankingTime, &m_Reset, &m_FirmwareMode, &m_Version, + &m_FixedParam, &m_FrameSync, &m_CloseStreamsOnShutdown, &m_InstancePointer, &m_ID, + &m_USBPath, + }; + + nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(*ppModuleHolder); + *ppModuleHolder = NULL; + return (nRetVal); + } + + // configure it from global file + if (m_strGlobalConfigFile[0] != '\0') + { + nRetVal = pModule->LoadConfigFromFile(m_strGlobalConfigFile); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceBase::CreateStreamImpl(strType, strName, pInitialSet); + XN_IS_STATUS_OK(nRetVal); + + // and configure it from global config file + nRetVal = ConfigureModuleFromGlobalFile(strName, strType); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // make sure reading from streams is turned on + if (!m_ReadData.GetValue()) + { + nRetVal = m_ReadData.SetValue(TRUE); + XN_IS_STATUS_OK(nRetVal); + } + + XnDeviceStream* pStream; + XnSensorStreamHelper* pHelper; + + // create stream + if (strcmp(StreamType, XN_STREAM_TYPE_DEPTH) == 0) + { + XnSensorDepthStream* pDepthStream; + XN_VALIDATE_NEW(pDepthStream, XnSensorDepthStream, GetUSBPath(), StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); + pStream = pDepthStream; + pHelper = pDepthStream->GetHelper(); + } + else if (strcmp(StreamType, XN_STREAM_TYPE_IMAGE) == 0) + { + XnSensorImageStream* pImageStream; + XN_VALIDATE_NEW(pImageStream, XnSensorImageStream, GetUSBPath(), StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); + pStream = pImageStream; + pHelper = pImageStream->GetHelper(); + } + else if (strcmp(StreamType, XN_STREAM_TYPE_IR) == 0) + { + XnSensorIRStream* pIRStream; + XN_VALIDATE_NEW(pIRStream, XnSensorIRStream, GetUSBPath(), StreamName, &m_Objects, m_NumberOfBuffers.GetValue()); + pStream = pIRStream; + pHelper = pIRStream->GetHelper(); + } + else if (strcmp(StreamType, XN_STREAM_TYPE_AUDIO) == 0) + { + XnSensorAudioStream* pAudioStream; + XN_VALIDATE_NEW(pAudioStream, XnSensorAudioStream, GetUSBPath(), StreamName, &m_Objects); + pStream = pAudioStream; + pHelper = pAudioStream->GetHelper(); + } + else + { + XN_LOG_WARNING_RETURN(XN_STATUS_UNSUPPORTED_STREAM, XN_MASK_DEVICE_SENSOR, "Unsupported stream type: %s", StreamType); + } + + *ppStreamHolder = XN_NEW(XnSensorStreamHolder, pStream, pHelper); + + return (XN_STATUS_OK); +} + +void XnSensor::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) +{ + XN_DELETE(pStreamHolder->GetModule()); + XN_DELETE(pStreamHolder); +} + +XnStatus XnSensor::OpenAllStreams() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Opening all streams..."); + + // take a list of all the streams + const XnChar* astrStreams[XN_SENSOR_MAX_STREAM_COUNT]; + XnUInt32 nStreamCount = XN_SENSOR_MAX_STREAM_COUNT; + XnDeviceStream* apStreams[XN_SENSOR_MAX_STREAM_COUNT]; + XnSensorStreamHolder* apSensorStreams[XN_SENSOR_MAX_STREAM_COUNT]; + + nRetVal = GetStreamNames(astrStreams, &nStreamCount); + XN_IS_STATUS_OK(nRetVal); + + for (XnUInt32 i = 0; i < nStreamCount; ++i) + { + XnDeviceModuleHolder* pHolder; + nRetVal = FindStream(astrStreams[i], &pHolder); + XN_IS_STATUS_OK(nRetVal); + + apSensorStreams[i] = (XnSensorStreamHolder*)(pHolder); + apStreams[i] = apSensorStreams[i]->GetStream(); + } + + // NOTE: the following is an ugly patch. When depth and IR both exist, Depth stream MUST be configured + // and opened BEFORE IR stream. So, generally, if one of the streams is depth, we move it to be first. + for (XnUInt32 i = 1; i < nStreamCount; ++i) + { + if (strcmp(apStreams[i]->GetType(), XN_STREAM_TYPE_DEPTH) == 0) + { + // switch it with the one in location 0 + const XnChar* strTempName = astrStreams[0]; + XnDeviceStream* pTempStream = apStreams[0]; + XnSensorStreamHolder* pTempHolder = apSensorStreams[0]; + + astrStreams[0] = astrStreams[i]; + apStreams[0] = apStreams[i]; + apSensorStreams[0] = apSensorStreams[i]; + + astrStreams[i] = strTempName; + apStreams[i] = pTempStream; + apSensorStreams[i] = pTempHolder; + break; + } + } + + // now configure them all + for (XnUInt32 i = 0; i < nStreamCount; ++i) + { + if (!apStreams[i]->IsOpen()) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Configuring stream %s...", apStreams[i]->GetName()); + nRetVal = apSensorStreams[i]->Configure(); + XN_IS_STATUS_OK(nRetVal); + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s is configured", apStreams[i]->GetName()); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Stream %s is already open.", apStreams[i]->GetName()); + } + } + + // and open them all + for (XnUInt32 i = 0; i < nStreamCount; ++i) + { + if (!apStreams[i]->IsOpen()) + { + nRetVal = apSensorStreams[i]->FinalOpen(); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::ReadStream(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check internal state + nRetVal = CheckIfReadingAllowed(); + XN_IS_STATUS_OK(nRetVal); + + // call base + nRetVal = XnDeviceBase::ReadStream(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::GetSharedBufferPool(const XnChar* strStream, XnSharedMemoryBufferPool** ppBufferPool) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModuleHolder* pHolder; + nRetVal = FindStream(strStream, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHolder* pSensorStreamHolder = (XnSensorStreamHolder*)(pHolder); + *ppBufferPool = pSensorStreamHolder->GetSharedBufferPool(); + + return (XN_STATUS_OK); +} + +XnBool XnSensor::HasSynchedFrameArrived(const XnChar* strDepthStream, const XnChar* strImageStream) +{ + // find both streams + XnDeviceStream* pDepth; + XnDeviceStream* pImage; + + if (XN_STATUS_OK != FindStream(strDepthStream, &pDepth)) + return FALSE; + + if (XN_STATUS_OK != FindStream(strImageStream, &pImage)) + return FALSE; + + XnUInt32 nThreshold = XN_SENSOR_FRAME_SYNC_MAX_DIFF; + if (IsHighResTimestamps()) + nThreshold *= 1000; + + // wait for both to advance, and time difference to be less than threshold + XnInt32 nTimestampDiff = XnInt32(pDepth->GetLastTimestamp() - pImage->GetLastTimestamp()); + + XnBool bConditionMet = ( + pDepth->IsNewDataAvailable() && + pImage->IsNewDataAvailable() && + (XnUInt32)abs(nTimestampDiff) <= nThreshold + ); + + if (xnLogIsDumpMaskEnabled(XN_DUMP_FRAME_SYNC)) + { + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_FrameSyncDump, "%llu,%u,%llu,%u,%llu,%s\n", + nNow, + pDepth->IsNewDataAvailable(), + pDepth->GetLastTimestamp(), + pImage->IsNewDataAvailable(), + pImage->GetLastTimestamp(), + bConditionMet ? "OK" : "Waiting"); + } + + return bConditionMet; +} + +XnBool XnSensor::HasSynchedFrameArrived(void* pCookie) +{ + XnWaitForSycnhedFrameData* pData = (XnWaitForSycnhedFrameData*)pCookie; + return pData->pThis->HasSynchedFrameArrived(pData->strDepthStream, pData->strImageStream); +} + +XnStatus XnSensor::WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_FrameSync.GetValue() == TRUE) + { + // FrameSync is on. check if we have both the image and the depth stream + XnStreamData* apStreamData[XN_DEVICE_BASE_MAX_STREAMS_COUNT]; + XnUInt32 nCount = XN_DEVICE_BASE_MAX_STREAMS_COUNT; + + nRetVal = XnStreamDataSetCopyToArray(pSet, apStreamData, &nCount); + XN_IS_STATUS_OK(nRetVal); + + const XnChar* strImageName = NULL; + const XnChar* strDepthName = NULL; + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + + for (XnUInt32 i = 0; i < nCount; ++i) + { + nRetVal = GetProperty(apStreamData[i]->StreamName, XN_STREAM_PROPERTY_TYPE, strType); + XN_IS_STATUS_OK(nRetVal); + + if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) + { + strDepthName = apStreamData[i]->StreamName; + } + else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) + { + strImageName = apStreamData[i]->StreamName; + } + + // if both are present, wait for frame sync + if (strImageName != NULL && strDepthName != NULL) + { + XnWaitForSycnhedFrameData WaitData; + WaitData.pThis = this; + WaitData.strDepthStream = strDepthName; + WaitData.strImageStream = strImageName; + + nRetVal = xnOSWaitForCondition(hNewDataEvent, XN_DEVICE_READ_FRAME_TIMEOUT, &XnSensor::HasSynchedFrameArrived, &WaitData); + if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) + { + xnLogError(XN_MASK_DDK, "Not responding - Didn't get any synced frame"); + return (XN_STATUS_DEVICE_FRAMES_NOT_SYNCHED); + } + else + { + XN_IS_STATUS_OK(nRetVal); + } + } + } // for loop + } + + // if we reached here, either frame sync is off, or one of the streams is not read from. + // either way, we should just wait for the primary stream. + nRetVal = XnDeviceBase::WaitForPrimaryStream(hNewDataEvent, pSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::Read(XnStreamDataSet* pStreamOutputSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check internal state + nRetVal = CheckIfReadingAllowed(); + XN_IS_STATUS_OK(nRetVal); + + // call base + nRetVal = XnDeviceBase::Read(pStreamOutputSet); + XN_IS_STATUS_OK(nRetVal); + + m_FPS.MarkReadCalled(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::WriteStream(const XnStreamData* pStreamOutput) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnSensor::Write(const XnStreamDataSet* pStreamOutputSet) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnSensor::Seek(XnUInt64 nTimestamp) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnSensor::SeekFrame(XnUInt32 nFrameID) +{ + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); +} + +XnStatus XnSensor::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(csINIFilePath); + XN_VALIDATE_INPUT_PTR(csSectionName); + + // we first need to configure the USB interface (we want to do so BEFORE creating streams) + nRetVal = m_Interface.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_NumberOfBuffers.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_ReadFromEP1.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_ReadFromEP2.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_ReadFromEP3.ReadValueFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + // now create all streams + nRetVal = CreateStreamsFromFile(csINIFilePath, csSectionName); + XN_IS_STATUS_OK(nRetVal); + + // now configure DEVICE module (primary stream, global mirror, etc.) + nRetVal = DeviceModule()->LoadConfigFromFile(csINIFilePath, XN_MODULE_NAME_DEVICE); + XN_IS_STATUS_OK(nRetVal); + + // and now configure the streams + XnDeviceModuleHolderList streams; + nRetVal = GetStreamsList(streams); + XN_IS_STATUS_OK(nRetVal); + + for (XnDeviceModuleHolderList::Iterator it = streams.begin(); it != streams.end(); ++it) + { + XnDeviceModuleHolder* pHolder = *it; + nRetVal = pHolder->GetModule()->LoadConfigFromFile(csINIFilePath); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::CheckIfReadingAllowed() +{ + return GetErrorState(); +} + +XnStatus XnSensor::InitReading() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // open data endpoints + nRetVal = m_SensorIO.OpenDataEndPoints((XnSensorUsbInterface)m_Interface.GetValue()); + XN_IS_STATUS_OK(nRetVal); + + // take frequency information + XnFrequencyInformation FrequencyInformation; + + nRetVal = XnHostProtocolAlgorithmParams(&m_DevicePrivateData, XN_HOST_PROTOCOL_ALGORITHM_FREQUENCY, &FrequencyInformation, sizeof(XnFrequencyInformation), (XnResolutions)0, 0); + if (nRetVal != XN_STATUS_OK) + return nRetVal; + + m_DevicePrivateData.fDeviceFrequency = XN_PREPARE_VAR_FLOAT_IN_BUFFER(FrequencyInformation.fDeviceFrequency); + + // Init Dumps + m_DevicePrivateData.BandwidthDump = XN_DUMP_CLOSED; + xnDumpInit(&m_DevicePrivateData.BandwidthDump, XN_DUMP_BANDWIDTH, "Timestamp,Frame Type,Frame ID,Size\n", "Bandwidth.csv"); + m_DevicePrivateData.TimestampsDump = XN_DUMP_CLOSED; + xnDumpInit(&m_DevicePrivateData.TimestampsDump, XN_DUMP_TIMESTAMPS, "Host Time (us),Stream,Device TS,Time (ms),Comments\n", "Timestamps.csv"); + m_DevicePrivateData.MiniPacketsDump = XN_DUMP_CLOSED; + xnDumpInit(&m_DevicePrivateData.MiniPacketsDump, XN_DUMP_MINI_PACKETS, "HostTS,Type,ID,Size,Timestamp\n", "MiniPackets.csv"); + + m_DevicePrivateData.nGlobalReferenceTS = 0; + nRetVal = xnOSCreateCriticalSection(&m_DevicePrivateData.hEndPointsCS); + XN_IS_STATUS_OK(nRetVal); + + // NOTE: when we go up, some streams might be open, and so we'll receive lots of garbage. + // wait till streams are turned off, and then start reading. +// pDevicePrivateData->bIgnoreDataPackets = TRUE; + + // open input threads + nRetVal = XnDeviceSensorOpenInputThreads(GetDevicePrivateData(), (XnBool)m_ReadFromEP1.GetValue(), (XnBool)m_ReadFromEP2.GetValue(), (XnBool)m_ReadFromEP3.GetValue()); + XN_IS_STATUS_OK(nRetVal); + + + return XN_STATUS_OK; +} + + +XnStatus XnSensor::ParseConnectionString(const XnChar* csConnectionString, XnChar* csSensorID, XnUInt32* pnBoardID) +{ + XnStatus nRetVal = XN_STATUS_OK; + +/* const XnChar* cpSepPos = strstr(csConnectionString, XN_DEVICE_SENSOR_BOARDID_SEP); + if (cpSepPos == NULL) + { + return (XN_STATUS_IO_INVALID_CONNECTION_STRING); + } + + XnUInt32 nSepPos = cpSepPos - csConnectionString; + + xnOSMemSet(csSensorID, 0, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); + + nRetVal = xnOSStrNCopy(csSensorID, csConnectionString, nSepPos, XN_SENSOR_PROTOCOL_SENSOR_ID_LENGTH); + XN_IS_STATUS_OK(nRetVal); + + *pnBoardID = atoi(cpSepPos + 1); +*/ + return (XN_STATUS_OK); +} + +XnStatus XnSensor::ValidateSensorID(XnChar* csSensorID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (strcmp(csSensorID, XN_DEVICE_SENSOR_DEFAULT_ID) != 0) + { + if (strcmp(csSensorID, GetFixedParams()->GetSensorSerial()) != 0) + { + return (XN_STATUS_IO_DEVICE_WRONG_SERIAL); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::ResolveGlobalConfigFileName(XnChar* strConfigFile, XnUInt32 nBufSize, const XnChar* strConfigDir) +{ + XnUInt32 nWritten = 0; + return xnOSStrFormat(strConfigFile, nBufSize, &nWritten, "%s%s%s", strConfigDir, XN_FILE_DIR_SEP, XN_GLOBAL_CONFIG_FILE_NAME); +} + +XnStatus XnSensor::SetGlobalConfigFile(const XnChar* strConfigFile) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSStrCopy(m_strGlobalConfigFile, strConfigFile, XN_FILE_MAX_PATH); + XN_IS_STATUS_OK(nRetVal); + + XnBool bExists; + nRetVal = xnOSDoesFileExist(m_strGlobalConfigFile, &bExists); + XN_IS_STATUS_OK(nRetVal); + + if (!bExists) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Global configuration file '%s' was not found.", m_strGlobalConfigFile); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::ConfigureModuleFromGlobalFile(const XnChar* strModule, const XnChar* strSection /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDeviceModule* pModule; + nRetVal = FindModule(strModule, &pModule); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pModule->LoadConfigFromFile(m_strGlobalConfigFile, strSection); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::GetFirmwareParam(XnInnerParamData* pParam) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnHostProtocolGetParam(&m_DevicePrivateData, pParam->nParam, pParam->nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::GetCmosBlankingUnits(XnCmosBlankingUnits* pBlanking) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) + { + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); + } + + nRetVal = XnHostProtocolGetCmosBlanking(&m_DevicePrivateData, pBlanking->nCmosID, &pBlanking->nUnits); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::GetCmosBlankingTime(XnCmosBlankingTime* pBlanking) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check version + if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) + { + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); + } + + // get value in units + XnCmosBlankingUnits blankingUnits; + blankingUnits.nCmosID = pBlanking->nCmosID; + nRetVal = GetCmosBlankingUnits(&blankingUnits); + XN_IS_STATUS_OK(nRetVal); + + // get coefficients + const XnCmosBlankingCoefficients* pCoeffs = m_CmosInfo.GetBlankingCoefficients(pBlanking->nCmosID); + + // translate to time + pBlanking->nTimeInMilliseconds = (pCoeffs->fA * blankingUnits.nUnits + pCoeffs->fB)/1000; + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::GetFirmwareMode(XnParamCurrentMode* pnMode) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_Firmware.GetInfo()->nFWVer == XN_SENSOR_FW_VER_0_17) + { + *pnMode = m_Firmware.GetInfo()->nCurrMode; + } + else + { + XnUInt16 nMode; + nRetVal = XnHostProtocolGetMode(&m_DevicePrivateData, nMode); + XN_IS_STATUS_OK(nRetVal); + + switch (nMode) + { + case XN_HOST_PROTOCOL_MODE_PS: + *pnMode = XN_MODE_PS; + break; + case XN_HOST_PROTOCOL_MODE_MAINTENANCE: + *pnMode = XN_MODE_MAINTENANCE; + break; + case XN_HOST_PROTOCOL_MODE_SAFE_MODE: + *pnMode = XN_MODE_SAFE_MODE; + break; + default: + printf("Got Unknown Firmware Mode %d\n", nMode); + return XN_STATUS_DEVICE_BAD_PARAM; + } + } + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::GetFixedParams(XnDynamicSizeBuffer* pBuffer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (pBuffer->nMaxSize < sizeof(XnFixedParams)) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + XnFixedParams fixed; + nRetVal = XnHostProtocolGetFixedParams(GetDevicePrivateData(), fixed); + XN_IS_STATUS_OK(nRetVal); + + xnOSMemCopy(pBuffer->pData, &fixed, sizeof(XnFixedParams)); + pBuffer->nDataSize = sizeof(XnFixedParams); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::SetErrorState(XnStatus errorState) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (errorState != GetErrorState()) + { + if (errorState == XN_STATUS_OK) + { + xnLogInfo(XN_MASK_DEVICE_SENSOR, "Device is back to normal state."); + } + else + { + xnLogError(XN_MASK_DEVICE_SENSOR, "Device has entered error mode: %s", xnGetStatusString(errorState)); + } + + nRetVal = m_ErrorState.UnsafeUpdateValue((XnUInt64)errorState); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetInterface(XnSensorUsbInterface nInterface) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // we don't allow change if requested value is specific and different than current + if (m_ReadData.GetValue() == TRUE && + nInterface != XN_SENSOR_USB_INTERFACE_DEFAULT && + nInterface != m_SensorIO.GetCurrentInterface()) + { + return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); + } + + nRetVal = m_Interface.UnsafeUpdateValue(nInterface); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetNumberOfBuffers(XnUInt32 nCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // This is a special func. It can only be changed BEFORE reading starts + if (m_ReadData.GetValue() == FALSE) + { + nRetVal = m_NumberOfBuffers.UnsafeUpdateValue(nCount); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // check it's the same value + if (nCount != m_NumberOfBuffers.GetValue()) + { + return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetReadEndpoint1(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // This is a special func. It can only be changed BEFORE reading starts + if (m_ReadData.GetValue() == FALSE) + { + nRetVal = m_ReadFromEP1.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // check it's the same value + if (bRead != m_ReadFromEP1.GetValue()) + { + return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetReadEndpoint2(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // This is a special func. It can only be changed BEFORE reading starts + if (m_ReadData.GetValue() == FALSE) + { + nRetVal = m_ReadFromEP2.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // check it's the same value + if (bRead != m_ReadFromEP2.GetValue()) + { + return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetReadEndpoint3(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // This is a special func. It can only be changed BEFORE reading starts + if (m_ReadData.GetValue() == FALSE) + { + nRetVal = m_ReadFromEP3.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // check it's the same value + if (bRead != m_ReadFromEP3.GetValue()) + { + return (XN_STATUS_DEVICE_PROPERTY_READ_ONLY); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetReadData(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!bRead) + { + return XN_STATUS_ERROR; + } + else + { + nRetVal = InitReading(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_ReadData.UnsafeUpdateValue(TRUE); + XN_IS_STATUS_OK(nRetVal); + + // no longer needed + m_ReadData.UpdateSetCallback(NULL, NULL); + } + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::SetFirmwareParam(const XnInnerParamData* pParam) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnHostProtocolSetParam(&m_DevicePrivateData, pParam->nParam, pParam->nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::SetCmosBlankingUnits(const XnCmosBlankingUnits* pBlanking) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) + { + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); + } + + nRetVal = XnHostProtocolSetCmosBlanking(&m_DevicePrivateData, pBlanking->nUnits, pBlanking->nCmosID, pBlanking->nNumberOfFrames); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetCmosBlankingTime(const XnCmosBlankingTime* pBlanking) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check version + if (m_Firmware.GetInfo()->nFWVer < XN_SENSOR_FW_VER_5_1) + { + return (XN_STATUS_IO_DEVICE_FUNCTION_NOT_SUPPORTED); + } + + // get coefficients + const XnCmosBlankingCoefficients* pCoeffs = m_CmosInfo.GetBlankingCoefficients(pBlanking->nCmosID); + + // translate to units request + XnCmosBlankingUnits blankingUnits; + blankingUnits.nCmosID = pBlanking->nCmosID; + blankingUnits.nNumberOfFrames = pBlanking->nNumberOfFrames; + blankingUnits.nUnits = XnUInt16((pBlanking->nTimeInMilliseconds*1000 - pCoeffs->fB)/pCoeffs->fA); + + nRetVal = SetCmosBlankingUnits(&blankingUnits); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::Reset(XnParamResetType nType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnHostProtocolReset(&m_DevicePrivateData, nType); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensor::SetFirmwareMode(XnParamCurrentMode nMode) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_Firmware.GetInfo()->nFWVer == XN_SENSOR_FW_VER_0_17) + { + m_Firmware.GetInfo()->nCurrMode = nMode; + return (XN_STATUS_OK); + } + + XnHostProtocolModeType nActualValue; + + switch (nMode) + { + case XN_MODE_PS: + nActualValue = XN_HOST_PROTOCOL_MODE_PS; + break; + case XN_MODE_MAINTENANCE: + nActualValue = XN_HOST_PROTOCOL_MODE_MAINTENANCE; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + nRetVal = XnHostProtocolSetMode(&m_DevicePrivateData, nActualValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensor::OnFrameSyncPropertyChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_ReadData.GetValue() == TRUE) + { + // decide firmware frame sync - both streams are on, and user asked for it + XnBool bFrameSync = ( + m_FrameSync.GetValue() == TRUE && + GetFirmware()->GetParams()->m_Stream0Mode.GetValue() == XN_VIDEO_STREAM_COLOR && + GetFirmware()->GetParams()->m_Stream1Mode.GetValue() == XN_VIDEO_STREAM_DEPTH + ); + + nRetVal = GetFirmware()->GetParams()->m_FrameSyncEnabled.SetValue(bFrameSync); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetInterfaceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->XnSensor::SetInterface((XnSensorUsbInterface)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetNumberOfBuffersCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->SetNumberOfBuffers((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint1Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->XnSensor::SetReadEndpoint1((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint2Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->XnSensor::SetReadEndpoint2((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetReadEndpoint3Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->XnSensor::SetReadEndpoint3((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetReadDataCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->XnSensor::SetReadData((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetFirmwareParamCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnInnerParamData); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->SetFirmwareParam((const XnInnerParamData*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetCmosBlankingUnitsCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingUnits); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->SetCmosBlankingUnits((const XnCmosBlankingUnits*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetCmosBlankingTimeCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingTime); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->SetCmosBlankingTime((const XnCmosBlankingTime*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::ResetCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->Reset((XnParamResetType)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::SetFirmwareModeCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->SetFirmwareMode((XnParamCurrentMode)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::GetFirmwareParamCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnInnerParamData); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->GetFirmwareParam((XnInnerParamData*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::GetCmosBlankingUnitsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingUnits); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->GetCmosBlankingUnits((XnCmosBlankingUnits*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::GetCmosBlankingTimeCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnCmosBlankingTime); + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->GetCmosBlankingTime((XnCmosBlankingTime*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::GetFirmwareModeCallback(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + XnParamCurrentMode nMode; + XnStatus nRetVal = pThis->GetFirmwareMode(&nMode); + XN_IS_STATUS_OK(nRetVal); + + *pnValue = nMode; + return XN_STATUS_OK; +} + +XnStatus XN_CALLBACK_TYPE XnSensor::FrameSyncPropertyChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnSensor* pThis = (XnSensor*)pCookie; + return pThis->OnFrameSyncPropertyChanged(); +} + +XnStatus XN_CALLBACK_TYPE XnSensor::GetFixedParamsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + XN_VALIDATE_GENERAL_BUFFER_TYPE(gbValue, XnDynamicSizeBuffer); + XnSensor* pThis = (XnSensor*)pCookie; + XnDynamicSizeBuffer* pBuffer = (XnDynamicSizeBuffer*)gbValue.pData; + return pThis->GetFixedParams(pBuffer); +} + +XnBool XN_CALLBACK_TYPE XnSensor::USBEventCallback(XnUSBEventType USBEventType, XnChar* cpDevPath, void* pCallbackData) +{ + XnSensor* pXnSensor = (XnSensor*)pCallbackData; + if (USBEventType == XN_USB_EVENT_DEVICE_DISCONNECT) + { + pXnSensor->SetErrorState(XN_STATUS_DEVICE_NOT_CONNECTED); + } + /*else + { + pXnSensor->SetErrorState(XN_STATUS_OK); + }*/ + //TODO: Uncomment this once we can deal with re-connections + + return TRUE; +} + diff --git a/Source/XnDeviceSensorV2/XnSensor.h b/Source/XnDeviceSensorV2/XnSensor.h index 5465f71..7c6202f 100644 --- a/Source/XnDeviceSensorV2/XnSensor.h +++ b/Source/XnDeviceSensorV2/XnSensor.h @@ -1,214 +1,217 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_H__ -#define __XN_SENSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnDeviceSensorIO.h" -#include "XnParams.h" -#include "XnDeviceSensor.h" -#include "XnSensorFixedParams.h" -#include "XnSensorFirmwareParams.h" -#include -#include "XnSensorFirmware.h" -#include "XnCmosInfo.h" -#include "IXnSensorStream.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_SENSOR_PROPERTY_INSTANCE_POINTER "InstancePointer" - -//--------------------------------------------------------------------------- -// XnSensor class -//--------------------------------------------------------------------------- -class XnSensor : public XnDeviceBase -{ - friend class XnSensorServer; - -public: - XnSensor(); - ~XnSensor(); - - static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); - static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); - - virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus Destroy(); - virtual XnStatus OpenAllStreams(); - virtual XnStatus ReadStream(XnStreamData* pStreamOutput); - virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet); - virtual XnStatus WriteStream(const XnStreamData* pStreamOutput); - virtual XnStatus Write(const XnStreamDataSet* pStreamOutputSet); - virtual XnStatus Seek(XnUInt64 nTimestamp); - virtual XnStatus SeekFrame(XnUInt32 nFrameID); - virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); - -public: - inline const XnSensorFixedParams* GetFixedParams() const { return &m_FixedParams; } - inline XnSensorFirmware* GetFirmware() { return &m_Firmware; } - inline XnSensorFPS* GetFPSCalculator() { return &m_FPS; } - - XnStatus SetCmosConfiguration(XnCMOSType nCmos, XnResolutions nRes, XnUInt32 nFPS); - - inline XnDevicePrivateData* GetDevicePrivateData() { return &m_DevicePrivateData; } - - XnStatus ConfigPropertyFromFile(XnStringProperty* pProperty, const XnChar* csINIFilePath, const XnChar* csSectionName); - XnStatus ConfigPropertyFromFile(XnIntProperty* pProperty, const XnChar* csINIFilePath, const XnChar* csSectionName); - - inline XnBool IsMiscSupported() const { return m_SensorIO.IsMiscEndpointSupported(); } - - XnStatus GetSharedBufferPool(const XnChar* strStream, XnSharedMemoryBufferPool** ppBufferPool); - - inline XnStatus GetErrorState() { return (XnStatus)m_ErrorState.GetValue(); } - XnStatus SetErrorState(XnStatus errorState); - - static XnStatus ResolveGlobalConfigFileName(XnChar* strConfigFile, XnUInt32 nBufSize, const XnChar* strConfigDir); - XnStatus SetGlobalConfigFile(const XnChar* strConfigFile); - XnStatus ConfigureModuleFromGlobalFile(const XnChar* strModule, const XnChar* strSection = NULL); - - -protected: - virtual XnStatus CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet); - - XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); - XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStream); - void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); - - XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); - -private: - XnStatus InitSensor(const XnDeviceConfig* pDeviceConfig); - XnStatus ParseConnectionString(const XnChar* csConnectionString, XnChar* csSensorID, XnUInt32* pnBoardID); - XnStatus ValidateSensorID(XnChar* csSensorID); - XnStatus ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamOutput); - XnStatus SetMirrorForModule(XnDeviceModule* pModule, XnUInt64 nValue); - XnStatus FindSensorStream(const XnChar* StreamName, IXnSensorStream** ppStream); - XnStatus CheckIfReadingAllowed(); - XnStatus InitReading(); - XnBool HasSynchedFrameArrived(const XnChar* strDepthStream, const XnChar* strImageStream); - XnStatus OnFrameSyncPropertyChanged(); - - - //--------------------------------------------------------------------------- - // Getters - //--------------------------------------------------------------------------- - XnStatus GetFirmwareParam(XnInnerParamData* pParam); - XnStatus GetCmosBlankingUnits(XnCmosBlankingUnits* pBlanking); - XnStatus GetCmosBlankingTime(XnCmosBlankingTime* pBlanking); - XnStatus GetFirmwareMode(XnParamCurrentMode* pnMode); - XnStatus GetLastRawFrame(const XnChar* strStream, XnUChar* pBuffer, XnUInt32 nDataSize); - XnStatus GetFixedParams(XnDynamicSizeBuffer* pBuffer); - - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - XnStatus SetInterface(XnSensorUsbInterface nInterface); - XnStatus SetNumberOfBuffers(XnUInt32 nCount); - XnStatus SetReadEndpoint1(XnBool bRead); - XnStatus SetReadEndpoint2(XnBool bRead); - XnStatus SetReadEndpoint3(XnBool bRead); - XnStatus SetReadData(XnBool bRead); - XnStatus SetFirmwareParam(const XnInnerParamData* pParam); - XnStatus SetCmosBlankingUnits(const XnCmosBlankingUnits* pBlanking); - XnStatus SetCmosBlankingTime(const XnCmosBlankingTime* pBlanking); - XnStatus Reset(XnParamResetType nType); - XnStatus SetFirmwareMode(XnParamCurrentMode nMode); - - //--------------------------------------------------------------------------- - // Callbacks - //--------------------------------------------------------------------------- - static XnStatus XN_CALLBACK_TYPE SetInterfaceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetNumberOfBuffersCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetReadEndpoint1Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetReadEndpoint2Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetReadEndpoint3Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetReadDataCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetFirmwareParamCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetCmosBlankingUnitsCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetCmosBlankingTimeCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ResetCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetFirmwareModeCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetFixedParamsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE FrameSyncPropertyChangedCallback(const XnProperty* pSender, void* pCookie); - static XnBool XN_CALLBACK_TYPE HasSynchedFrameArrived(void* pCookie); - static XnBool XN_CALLBACK_TYPE USBEventCallback(XnUSBEventType USBEventType, XnChar* cpDevPath, void* pCallbackData); - static XnStatus XN_CALLBACK_TYPE GetFirmwareParamCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCmosBlankingUnitsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetCmosBlankingTimeCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetFirmwareModeCallback(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie); - - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnActualIntProperty m_ErrorState; - XnActualIntProperty m_ResetSensorOnStartup; - XnActualIntProperty m_Interface; - XnActualIntProperty m_NumberOfBuffers; - XnActualIntProperty m_ReadFromEP1; - XnActualIntProperty m_ReadFromEP2; - XnActualIntProperty m_ReadFromEP3; - XnActualIntProperty m_ReadData; - XnActualIntProperty m_FrameSync; - XnActualIntProperty m_CloseStreamsOnShutdown; - XnGeneralProperty m_FirmwareParam; - XnGeneralProperty m_CmosBlankingUnits; - XnGeneralProperty m_CmosBlankingTime; - XnIntProperty m_Reset; - XnIntProperty m_FirmwareMode; - XnVersions m_VersionData; - XnActualGeneralProperty m_Version; - XnGeneralProperty m_FixedParam; - XnSensor* m_pThis; - XnActualGeneralProperty m_InstancePointer; - XnActualStringProperty m_ID; - - XnSensorFirmware m_Firmware; - XnDevicePrivateData m_DevicePrivateData; - XnSensorFixedParams m_FixedParams; - XnSensorFPS m_FPS; - XnCmosInfo m_CmosInfo; - XnSensorIO m_SensorIO; - - XnSensorObjects m_Objects; - - - XnDump m_FrameSyncDump; - XnBool m_bInitialized; - - XnIntPropertySynchronizer m_PropSynchronizer; - - XnChar m_strGlobalConfigFile[XN_FILE_MAX_PATH]; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_H__ +#define __XN_SENSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnDeviceSensorIO.h" +#include "XnParams.h" +#include "XnDeviceSensor.h" +#include "XnSensorFixedParams.h" +#include "XnSensorFirmwareParams.h" +#include +#include "XnSensorFirmware.h" +#include "XnCmosInfo.h" +#include "IXnSensorStream.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_PROPERTY_INSTANCE_POINTER "InstancePointer" + +//--------------------------------------------------------------------------- +// XnSensor class +//--------------------------------------------------------------------------- +class XnSensor : public XnDeviceBase +{ + friend class XnServerSensorInvoker; + +public: + XnSensor(); + ~XnSensor(); + + static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); + static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); + + virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus Destroy(); + virtual XnStatus OpenAllStreams(); + virtual XnStatus ReadStream(XnStreamData* pStreamOutput); + virtual XnStatus Read(XnStreamDataSet* pStreamOutputSet); + virtual XnStatus WriteStream(const XnStreamData* pStreamOutput); + virtual XnStatus Write(const XnStreamDataSet* pStreamOutputSet); + virtual XnStatus Seek(XnUInt64 nTimestamp); + virtual XnStatus SeekFrame(XnUInt32 nFrameID); + virtual XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); + +public: + inline const XnSensorFixedParams* GetFixedParams() const { return &m_FixedParams; } + inline XnSensorFirmware* GetFirmware() { return &m_Firmware; } + inline XnSensorFPS* GetFPSCalculator() { return &m_FPS; } + + XnStatus SetCmosConfiguration(XnCMOSType nCmos, XnResolutions nRes, XnUInt32 nFPS); + + inline XnDevicePrivateData* GetDevicePrivateData() { return &m_DevicePrivateData; } + + XnStatus ConfigPropertyFromFile(XnStringProperty* pProperty, const XnChar* csINIFilePath, const XnChar* csSectionName); + XnStatus ConfigPropertyFromFile(XnIntProperty* pProperty, const XnChar* csINIFilePath, const XnChar* csSectionName); + + inline XnBool IsMiscSupported() const { return m_SensorIO.IsMiscEndpointSupported(); } + + XnStatus GetSharedBufferPool(const XnChar* strStream, XnSharedMemoryBufferPool** ppBufferPool); + + inline XnStatus GetErrorState() { return (XnStatus)m_ErrorState.GetValue(); } + XnStatus SetErrorState(XnStatus errorState); + + static XnStatus ResolveGlobalConfigFileName(XnChar* strConfigFile, XnUInt32 nBufSize, const XnChar* strConfigDir); + XnStatus SetGlobalConfigFile(const XnChar* strConfigFile); + XnStatus ConfigureModuleFromGlobalFile(const XnChar* strModule, const XnChar* strSection = NULL); + + const XnChar* GetUSBPath() { return m_USBPath.GetValue(); } + + +protected: + virtual XnStatus CreateStreamImpl(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialSet); + + XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); + XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStream); + void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); + + XnStatus WaitForPrimaryStream(XN_EVENT_HANDLE hNewDataEvent, XnStreamDataSet* pSet); + +private: + XnStatus InitSensor(const XnDeviceConfig* pDeviceConfig); + XnStatus ParseConnectionString(const XnChar* csConnectionString, XnChar* csSensorID, XnUInt32* pnBoardID); + XnStatus ValidateSensorID(XnChar* csSensorID); + XnStatus ReadFromStreamImpl(XnDeviceStream* pStream, XnStreamData* pStreamOutput); + XnStatus SetMirrorForModule(XnDeviceModule* pModule, XnUInt64 nValue); + XnStatus FindSensorStream(const XnChar* StreamName, IXnSensorStream** ppStream); + XnStatus CheckIfReadingAllowed(); + XnStatus InitReading(); + XnBool HasSynchedFrameArrived(const XnChar* strDepthStream, const XnChar* strImageStream); + XnStatus OnFrameSyncPropertyChanged(); + + + //--------------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------------- + XnStatus GetFirmwareParam(XnInnerParamData* pParam); + XnStatus GetCmosBlankingUnits(XnCmosBlankingUnits* pBlanking); + XnStatus GetCmosBlankingTime(XnCmosBlankingTime* pBlanking); + XnStatus GetFirmwareMode(XnParamCurrentMode* pnMode); + XnStatus GetLastRawFrame(const XnChar* strStream, XnUChar* pBuffer, XnUInt32 nDataSize); + XnStatus GetFixedParams(XnDynamicSizeBuffer* pBuffer); + + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + XnStatus SetInterface(XnSensorUsbInterface nInterface); + XnStatus SetNumberOfBuffers(XnUInt32 nCount); + XnStatus SetReadEndpoint1(XnBool bRead); + XnStatus SetReadEndpoint2(XnBool bRead); + XnStatus SetReadEndpoint3(XnBool bRead); + XnStatus SetReadData(XnBool bRead); + XnStatus SetFirmwareParam(const XnInnerParamData* pParam); + XnStatus SetCmosBlankingUnits(const XnCmosBlankingUnits* pBlanking); + XnStatus SetCmosBlankingTime(const XnCmosBlankingTime* pBlanking); + XnStatus Reset(XnParamResetType nType); + XnStatus SetFirmwareMode(XnParamCurrentMode nMode); + + //--------------------------------------------------------------------------- + // Callbacks + //--------------------------------------------------------------------------- + static XnStatus XN_CALLBACK_TYPE SetInterfaceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetNumberOfBuffersCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetReadEndpoint1Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetReadEndpoint2Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetReadEndpoint3Callback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetReadDataCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetFirmwareParamCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetCmosBlankingUnitsCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetCmosBlankingTimeCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ResetCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetFirmwareModeCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetFixedParamsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE FrameSyncPropertyChangedCallback(const XnProperty* pSender, void* pCookie); + static XnBool XN_CALLBACK_TYPE HasSynchedFrameArrived(void* pCookie); + static XnBool XN_CALLBACK_TYPE USBEventCallback(XnUSBEventType USBEventType, XnChar* cpDevPath, void* pCallbackData); + static XnStatus XN_CALLBACK_TYPE GetFirmwareParamCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCmosBlankingUnitsCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetCmosBlankingTimeCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetFirmwareModeCallback(const XnIntProperty* pSender, XnUInt64* pnValue, void* pCookie); + + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnActualIntProperty m_ErrorState; + XnActualIntProperty m_ResetSensorOnStartup; + XnActualIntProperty m_Interface; + XnActualIntProperty m_NumberOfBuffers; + XnActualIntProperty m_ReadFromEP1; + XnActualIntProperty m_ReadFromEP2; + XnActualIntProperty m_ReadFromEP3; + XnActualIntProperty m_ReadData; + XnActualIntProperty m_FrameSync; + XnActualIntProperty m_CloseStreamsOnShutdown; + XnGeneralProperty m_FirmwareParam; + XnGeneralProperty m_CmosBlankingUnits; + XnGeneralProperty m_CmosBlankingTime; + XnIntProperty m_Reset; + XnIntProperty m_FirmwareMode; + XnVersions m_VersionData; + XnActualGeneralProperty m_Version; + XnGeneralProperty m_FixedParam; + XnSensor* m_pThis; + XnActualGeneralProperty m_InstancePointer; + XnActualStringProperty m_ID; + XnActualStringProperty m_USBPath; + + XnSensorFirmware m_Firmware; + XnDevicePrivateData m_DevicePrivateData; + XnSensorFixedParams m_FixedParams; + XnSensorFPS m_FPS; + XnCmosInfo m_CmosInfo; + XnSensorIO m_SensorIO; + + XnSensorObjects m_Objects; + + + XnDump m_FrameSyncDump; + XnBool m_bInitialized; + + XnIntPropertySynchronizer m_PropSynchronizer; + + XnChar m_strGlobalConfigFile[XN_FILE_MAX_PATH]; +}; + #endif //__XN_SENSOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorAudioGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorAudioGenerator.cpp index 7828258..5f627a5 100644 --- a/Source/XnDeviceSensorV2/XnSensorAudioGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorAudioGenerator.cpp @@ -1,191 +1,191 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorAudioGenerator.h" - -//--------------------------------------------------------------------------- -// XnSensorAudioGenerator class -//--------------------------------------------------------------------------- -XnSensorAudioGenerator::XnSensorAudioGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorGenerator(context, sensor, pSensor, strStreamName) -{ -} - -XnStatus XnSensorAudioGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorGenerator::Init(); - XN_IS_STATUS_OK(nRetVal); - - // create supported modes list - XnUInt8 aSupportedChannels[] = { 1, 2 }; - XnUInt32 nSupportedChannels = sizeof(aSupportedChannels)/sizeof(XnUInt8); - - XnUInt16 aSupportedBitsPerSample[] = { 16 }; - XnUInt32 nSupportedBitsPerSample = sizeof(aSupportedBitsPerSample)/sizeof(XnUInt16); - - XnUInt32 aSupportedSampleRates[] = - { - XN_SAMPLE_RATE_8K, - XN_SAMPLE_RATE_11K, - XN_SAMPLE_RATE_12K, - XN_SAMPLE_RATE_16K, - XN_SAMPLE_RATE_22K, - XN_SAMPLE_RATE_24K, - XN_SAMPLE_RATE_32K, - XN_SAMPLE_RATE_44K, - XN_SAMPLE_RATE_48K, - }; - XnUInt32 nSupportedSampleRates = sizeof(aSupportedSampleRates)/sizeof(XnUInt32); - - for (XnUInt iChannel = 0; iChannel < nSupportedChannels; ++iChannel) - { - for (XnUInt iBitsPerSample = 0; iBitsPerSample < nSupportedBitsPerSample; ++iBitsPerSample) - { - for (XnUInt iSampleRate = 0; iSampleRate < nSupportedSampleRates; ++iSampleRate) - { - XnWaveOutputMode Mode; - Mode.nChannels = aSupportedChannels[iChannel]; - Mode.nBitsPerSample = aSupportedBitsPerSample[iBitsPerSample]; - Mode.nSampleRate = aSupportedSampleRates[iSampleRate]; - nRetVal = m_SupportedModes.AddLast(Mode); - XN_IS_STATUS_OK(nRetVal); - } - } - } - - return (XN_STATUS_OK); -} - -XnBool XnSensorAudioGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return FALSE; -} - -XnUChar* XnSensorAudioGenerator::GetAudioBuffer() -{ - return (XnUChar*)m_pStreamData->pData; -} - -XnUInt32 XnSensorAudioGenerator::GetSupportedWaveOutputModesCount() -{ - return m_SupportedModes.Size(); -} - -XnStatus XnSensorAudioGenerator::GetSupportedWaveOutputModes(XnWaveOutputMode aSupportedModes[], XnUInt32& nCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(aSupportedModes); - - if (nCount < m_SupportedModes.Size()) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - XnUInt32 i = 0; - for (XnWaveOutputModeList::Iterator it = m_SupportedModes.begin(); it != m_SupportedModes.end(); ++it, ++i) - { - aSupportedModes[i] = *it; - } - - nCount = m_SupportedModes.Size(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioGenerator::SetWaveOutputMode(const XnWaveOutputMode& OutputMode) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (OutputMode.nBitsPerSample != 16) - { - return XN_STATUS_INVALID_OPERATION; - } - - XN_PROPERTY_SET_CREATE_ON_STACK(props); - XnPropertySetAddModule(&props, m_strModule); - XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_SAMPLE_RATE, OutputMode.nSampleRate); - XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, OutputMode.nChannels); - - nRetVal = m_pSensor->BatchConfig(&props); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioGenerator::GetWaveOutputMode(XnWaveOutputMode& OutputMode) -{ - XnUInt64 nValue; - OutputMode.nBitsPerSample = 16; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_SAMPLE_RATE, &nValue); - OutputMode.nSampleRate = (XnUInt32)nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, &nValue); - OutputMode.nChannels = (XnUInt8)nValue; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioGenerator::RegisterToWaveOutputModeChanges(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_SAMPLE_RATE, - XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorAudioGenerator::UnregisterFromWaveOutputModeChanges(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorAudioGenerator::FilterProperties(XnActualPropertiesHash* pHash) -{ - XnSensorGenerator::FilterProperties(pHash); - pHash->Remove(XN_STREAM_PROPERTY_SAMPLE_RATE); - pHash->Remove(XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS); -} - -//--------------------------------------------------------------------------- -// XnExportedSensorAudioGenerator class -//--------------------------------------------------------------------------- -XnExportedSensorAudioGenerator::XnExportedSensorAudioGenerator() : - XnExportedSensorGenerator(XN_NODE_TYPE_AUDIO, XN_STREAM_TYPE_AUDIO) -{} - -XnSensorGenerator* XnExportedSensorAudioGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) -{ - return XN_NEW(XnSensorAudioGenerator, context, sensor, pSensor, strStreamName); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorAudioGenerator.h" + +//--------------------------------------------------------------------------- +// XnSensorAudioGenerator class +//--------------------------------------------------------------------------- +XnSensorAudioGenerator::XnSensorAudioGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorGenerator(context, sensor, pSensor, strStreamName) +{ +} + +XnStatus XnSensorAudioGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorGenerator::Init(); + XN_IS_STATUS_OK(nRetVal); + + // create supported modes list + XnUInt8 aSupportedChannels[] = { 1, 2 }; + XnUInt32 nSupportedChannels = sizeof(aSupportedChannels)/sizeof(XnUInt8); + + XnUInt16 aSupportedBitsPerSample[] = { 16 }; + XnUInt32 nSupportedBitsPerSample = sizeof(aSupportedBitsPerSample)/sizeof(XnUInt16); + + XnUInt32 aSupportedSampleRates[] = + { + XN_SAMPLE_RATE_8K, + XN_SAMPLE_RATE_11K, + XN_SAMPLE_RATE_12K, + XN_SAMPLE_RATE_16K, + XN_SAMPLE_RATE_22K, + XN_SAMPLE_RATE_24K, + XN_SAMPLE_RATE_32K, + XN_SAMPLE_RATE_44K, + XN_SAMPLE_RATE_48K, + }; + XnUInt32 nSupportedSampleRates = sizeof(aSupportedSampleRates)/sizeof(XnUInt32); + + for (XnUInt iChannel = 0; iChannel < nSupportedChannels; ++iChannel) + { + for (XnUInt iBitsPerSample = 0; iBitsPerSample < nSupportedBitsPerSample; ++iBitsPerSample) + { + for (XnUInt iSampleRate = 0; iSampleRate < nSupportedSampleRates; ++iSampleRate) + { + XnWaveOutputMode Mode; + Mode.nChannels = aSupportedChannels[iChannel]; + Mode.nBitsPerSample = aSupportedBitsPerSample[iBitsPerSample]; + Mode.nSampleRate = aSupportedSampleRates[iSampleRate]; + nRetVal = m_SupportedModes.AddLast(Mode); + XN_IS_STATUS_OK(nRetVal); + } + } + } + + return (XN_STATUS_OK); +} + +XnBool XnSensorAudioGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return FALSE; +} + +XnUChar* XnSensorAudioGenerator::GetAudioBuffer() +{ + return (XnUChar*)m_pStreamData->pData; +} + +XnUInt32 XnSensorAudioGenerator::GetSupportedWaveOutputModesCount() +{ + return m_SupportedModes.Size(); +} + +XnStatus XnSensorAudioGenerator::GetSupportedWaveOutputModes(XnWaveOutputMode aSupportedModes[], XnUInt32& nCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(aSupportedModes); + + if (nCount < m_SupportedModes.Size()) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + XnUInt32 i = 0; + for (XnWaveOutputModeList::Iterator it = m_SupportedModes.begin(); it != m_SupportedModes.end(); ++it, ++i) + { + aSupportedModes[i] = *it; + } + + nCount = m_SupportedModes.Size(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioGenerator::SetWaveOutputMode(const XnWaveOutputMode& OutputMode) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (OutputMode.nBitsPerSample != 16) + { + return XN_STATUS_INVALID_OPERATION; + } + + XN_PROPERTY_SET_CREATE_ON_STACK(props); + XnPropertySetAddModule(&props, m_strModule); + XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_SAMPLE_RATE, OutputMode.nSampleRate); + XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, OutputMode.nChannels); + + nRetVal = m_pSensor->BatchConfig(&props); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioGenerator::GetWaveOutputMode(XnWaveOutputMode& OutputMode) +{ + XnUInt64 nValue; + OutputMode.nBitsPerSample = 16; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_SAMPLE_RATE, &nValue); + OutputMode.nSampleRate = (XnUInt32)nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, &nValue); + OutputMode.nChannels = (XnUInt8)nValue; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioGenerator::RegisterToWaveOutputModeChanges(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_SAMPLE_RATE, + XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorAudioGenerator::UnregisterFromWaveOutputModeChanges(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorAudioGenerator::FilterProperties(XnActualPropertiesHash* pHash) +{ + XnSensorGenerator::FilterProperties(pHash); + pHash->Remove(XN_STREAM_PROPERTY_SAMPLE_RATE); + pHash->Remove(XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS); +} + +//--------------------------------------------------------------------------- +// XnExportedSensorAudioGenerator class +//--------------------------------------------------------------------------- +XnExportedSensorAudioGenerator::XnExportedSensorAudioGenerator() : + XnExportedSensorGenerator(XN_NODE_TYPE_AUDIO, XN_STREAM_TYPE_AUDIO) +{} + +XnSensorGenerator* XnExportedSensorAudioGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) +{ + return XN_NEW(XnSensorAudioGenerator, context, sensor, pSensor, strStreamName); +} diff --git a/Source/XnDeviceSensorV2/XnSensorAudioGenerator.h b/Source/XnDeviceSensorV2/XnSensorAudioGenerator.h index 682c2c3..7463cf8 100644 --- a/Source/XnDeviceSensorV2/XnSensorAudioGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorAudioGenerator.h @@ -1,76 +1,76 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_AUDIO_GENERATOR_H__ -#define __XN_SENSOR_AUDIO_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorGenerator.h" -#include "XnExportedSensorGenerator.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorAudioGenerator : - public XnSensorGenerator, - virtual public xn::ModuleAudioGenerator -{ -public: - XnSensorAudioGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - - XnStatus Init(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - XnUChar* GetAudioBuffer(); - XnUInt32 GetSupportedWaveOutputModesCount(); - XnStatus GetSupportedWaveOutputModes(XnWaveOutputMode aSupportedModes[], XnUInt32& nCount); - XnStatus SetWaveOutputMode(const XnWaveOutputMode& OutputMode); - XnStatus GetWaveOutputMode(XnWaveOutputMode& OutputMode); - XnStatus RegisterToWaveOutputModeChanges(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromWaveOutputModeChanges(XnCallbackHandle hCallback); - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); - -private: - XN_DECLARE_LIST(XnWaveOutputMode, XnWaveOutputModeList); - - XnWaveOutputModeList m_SupportedModes; -}; - -class XnExportedSensorAudioGenerator : public XnExportedSensorGenerator -{ -public: - XnExportedSensorAudioGenerator(); - virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_AUDIO_GENERATOR_H__ +#define __XN_SENSOR_AUDIO_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorGenerator.h" +#include "XnExportedSensorGenerator.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorAudioGenerator : + public XnSensorGenerator, + virtual public xn::ModuleAudioGenerator +{ +public: + XnSensorAudioGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + + XnStatus Init(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + XnUChar* GetAudioBuffer(); + XnUInt32 GetSupportedWaveOutputModesCount(); + XnStatus GetSupportedWaveOutputModes(XnWaveOutputMode aSupportedModes[], XnUInt32& nCount); + XnStatus SetWaveOutputMode(const XnWaveOutputMode& OutputMode); + XnStatus GetWaveOutputMode(XnWaveOutputMode& OutputMode); + XnStatus RegisterToWaveOutputModeChanges(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromWaveOutputModeChanges(XnCallbackHandle hCallback); + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); + +private: + XN_DECLARE_LIST(XnWaveOutputMode, XnWaveOutputModeList); + + XnWaveOutputModeList m_SupportedModes; +}; + +class XnExportedSensorAudioGenerator : public XnExportedSensorGenerator +{ +public: + XnExportedSensorAudioGenerator(); + virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); +}; + #endif // __XN_SENSOR_AUDIO_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorAudioStream.cpp b/Source/XnDeviceSensorV2/XnSensorAudioStream.cpp index 23173f7..f37b174 100644 --- a/Source/XnDeviceSensorV2/XnSensorAudioStream.cpp +++ b/Source/XnDeviceSensorV2/XnSensorAudioStream.cpp @@ -1,538 +1,539 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorInit.h" -#include "XnSensorAudioStream.h" -#include "XnSensor.h" -#include "XnAudioProcessor.h" -#include - -#define XN_AUDIO_MAX_SAMPLE_RATE 48000 -#define XN_AUDIO_MAX_NUMBER_OF_CHANNELS 2 - -#define XN_AUDIO_STREAM_DEFAULT_VOLUME 12 -#define XN_AUDIO_STREAM_DEFAULT_SAMPLE_RATE 48000 -#define XN_AUDIO_STREAM_DEFAULT_NUMBER_OF_CHANNELS 2 -#define XN_AUDIO_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_PCM -#define XN_AUDIO_STREAM_DEFAULT_CHUNK_SIZE 2120 - -#define XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK 424 -#define XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO 180 - -XnSensorAudioStream::XnSensorAudioStream(const XnChar* StreamName, XnSensorObjects* pObjects) : - XnAudioStream(StreamName, XN_AUDIO_MAX_NUMBER_OF_CHANNELS), - m_Helper(pObjects), - m_LeftChannelVolume(XN_STREAM_PROPERTY_LEFT_CHANNEL_VOLUME, XN_AUDIO_STREAM_DEFAULT_VOLUME), - m_RightChannelVolume(XN_STREAM_PROPERTY_RIGHT_CHANNEL_VOLUME, XN_AUDIO_STREAM_DEFAULT_VOLUME), - m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME), - m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE), - m_hSharedMemory(NULL), - m_pSharedHeader(NULL) -{ - m_LeftChannelVolume.UpdateSetCallback(SetLeftChannelVolumeCallback, this); - m_RightChannelVolume.UpdateSetCallback(SetRightChannelVolumeCallback, this); - m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); -} - -XnStatus XnSensorAudioStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init base - nRetVal = XnAudioStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - // init helper - nRetVal = m_Helper.Init(this, this); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetReadChunkSize(XN_AUDIO_STREAM_DEFAULT_CHUNK_SIZE); - XN_IS_STATUS_OK(nRetVal); - - // add properties - XN_VALIDATE_ADD_PROPERTIES(this, &m_LeftChannelVolume, &m_RightChannelVolume, &m_SharedBufferName, &m_ActualRead); - - // check what's the firmware audio packet size - if (m_Helper.GetPrivateData()->SensorHandle.MiscConnection.bIsISO) - m_nOrigAudioPacketSize = XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO; - else - m_nOrigAudioPacketSize = XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK; - - // alloc buffer - nRetVal = ReallocBuffer(); - XN_IS_STATUS_OK(nRetVal); - - m_Helper.GetPrivateData()->pAudioCallback = NewDataCallback; - m_Helper.GetPrivateData()->pAudioCallbackCookie = this; - - // data processor - nRetVal = m_Helper.RegisterDataProcessorProperty(NumberOfChannelsProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::Free() -{ - m_Helper.Free(); - XnAudioStream::Free(); - if (m_hSharedMemory != NULL) - { - xnOSCloseSharedMemory(m_hSharedMemory); - m_hSharedMemory = NULL; - } - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::MapPropertiesToFirmware() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(SampleRateProperty(), GetFirmwareParams()->m_AudioSampleRate, FALSE, ConvertSampleRateToFirmwareRate)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(NumberOfChannelsProperty(), GetFirmwareParams()->m_AudioStereo, FALSE, ConvertNumberOfChannelsToStereo)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_LeftChannelVolume, GetFirmwareParams()->m_AudioLeftChannelGain, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_RightChannelVolume, GetFirmwareParams()->m_AudioRightChannelGain, TRUE)); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::ConfigureStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp); - - nRetVal = SetActualRead(TRUE); - XN_IS_STATUS_OK(nRetVal); - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(SampleRateProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(NumberOfChannelsProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_LeftChannelVolume)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_RightChannelVolume)); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::SetActualRead(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_ActualRead.GetValue() != bRead) - { - if (bRead) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB audio read thread..."); - nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificMiscUsb->nChunkReadBytes, XN_SENSOR_USB_MISC_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificMiscUsb); - XN_IS_STATUS_OK(nRetVal); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB audio read thread..."); - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp); - } - - nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::OpenStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_ON); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnAudioStream::Open(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::CloseStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnAudioStream::Close(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetActualRead(FALSE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::CreateDataProcessor(XnDataProcessor** ppProcessor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDataProcessor* pAudioProcessor; - XN_VALIDATE_NEW_AND_INIT(pAudioProcessor, XnAudioProcessor, this, &m_Helper, m_nOrigAudioPacketSize); - - *ppProcessor = pAudioProcessor; - - return XN_STATUS_OK; -} - -XnStatus XnSensorAudioStream::SetOutputFormat(XnOutputFormats nOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_PCM: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Output format %d, isn't supported by sensor audio stream!", nOutputFormat); - } - - nRetVal = XnAudioStream::SetOutputFormat(nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::SetSampleRate(XnSampleRate nSampleRate) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.BeforeSettingFirmwareParam(SampleRateProperty(), nSampleRate); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnAudioStream::SetSampleRate(nSampleRate); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(SampleRateProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::SetNumberOfChannels(XnUInt32 nNumberOfChannels) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.BeforeSettingFirmwareParam(NumberOfChannelsProperty(), nNumberOfChannels); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnAudioStream::SetNumberOfChannels(nNumberOfChannels); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ReallocBuffer(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(NumberOfChannelsProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::NewData() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); - - // check how many buffers we have - XnInt32 nAvailbalePackets = pDevicePrivateData->nAudioWriteIndex - pDevicePrivateData->nAudioReadIndex; - if (nAvailbalePackets < 0) - nAvailbalePackets += pDevicePrivateData->nAudioBufferNumOfPackets; - - if ((XnUInt32)nAvailbalePackets * pDevicePrivateData->nAudioPacketSize >= GetReadChunkSize()) - { - // update last write index (the last written byte) - m_pSharedHeader->nWritePacketIndex = pDevicePrivateData->nAudioWriteIndex; - // take first packet timestamp - NewDataAvailable(pDevicePrivateData->pAudioPacketsTimestamps[pDevicePrivateData->nAudioReadIndex], 0); - } - - return XN_STATUS_OK; -} - -XnStatus XnSensorAudioStream::ReadImpl(XnStreamData *pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); - - pStreamOutput->nDataSize = 0; - - XN_AUDIO_TYPE* pAudioBuf = (XN_AUDIO_TYPE*)pStreamOutput->pData; - - xnOSEnterCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); - - // check how many buffers we have - XnInt32 nAvailbalePackets = pDevicePrivateData->nAudioWriteIndex - pDevicePrivateData->nAudioReadIndex; - if (nAvailbalePackets < 0) - nAvailbalePackets += pDevicePrivateData->nAudioBufferNumOfPackets; - - // now check if stream frame buffer has enough space - if (GetRequiredDataSize() < (XnUInt32)nAvailbalePackets * pDevicePrivateData->nAudioPacketSize) - { - xnOSLeaveCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); - return (XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER_SIZE); - } - - // take first packet timestamp - pStreamOutput->nTimestamp = pDevicePrivateData->pAudioPacketsTimestamps[pDevicePrivateData->nAudioReadIndex]; - XnUChar* pPacketData = pDevicePrivateData->pAudioBuffer + (pDevicePrivateData->nAudioReadIndex * pDevicePrivateData->nAudioPacketSize); - - // copy - while (pDevicePrivateData->nAudioReadIndex != pDevicePrivateData->nAudioWriteIndex) - { - xnOSMemCopy(pAudioBuf, pPacketData, pDevicePrivateData->nAudioPacketSize); - pAudioBuf += pDevicePrivateData->nAudioPacketSize; - pStreamOutput->nDataSize += pDevicePrivateData->nAudioPacketSize; - - pDevicePrivateData->nAudioReadIndex++; - pPacketData += pDevicePrivateData->nAudioPacketSize; - if (pDevicePrivateData->nAudioReadIndex == pDevicePrivateData->nAudioBufferNumOfPackets) - { - pDevicePrivateData->nAudioReadIndex = 0; - pPacketData = pDevicePrivateData->pAudioBuffer; - } - } - - xnOSLeaveCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::ConvertNumberOfChannelsToStereo(XnUInt64 nSource, XnUInt64* pnDest) -{ - *pnDest = (nSource == 2); - return XN_STATUS_OK; -} - -XnStatus XnSensorAudioStream::ConvertStereoToNumberOfChannels(XnUInt64 nSource, XnUInt64* pnDest) -{ - *pnDest = nSource ? 2 : 1; - return XN_STATUS_OK; -} - -XnStatus XnSensorAudioStream::ConvertSampleRateToFirmwareRate(XnUInt64 nSource, XnUInt64* pnDest) -{ - switch (nSource) - { - case XN_SAMPLE_RATE_8K: - *pnDest = A2D_SAMPLE_RATE_8KHZ; - break; - case XN_SAMPLE_RATE_11K: - *pnDest = A2D_SAMPLE_RATE_11KHZ; - break; - case XN_SAMPLE_RATE_12K: - *pnDest = A2D_SAMPLE_RATE_12KHZ; - break; - case XN_SAMPLE_RATE_16K: - *pnDest = A2D_SAMPLE_RATE_16KHZ; - break; - case XN_SAMPLE_RATE_22K: - *pnDest = A2D_SAMPLE_RATE_22KHZ; - break; - case XN_SAMPLE_RATE_24K: - *pnDest = A2D_SAMPLE_RATE_24KHZ; - break; - case XN_SAMPLE_RATE_32K: - *pnDest = A2D_SAMPLE_RATE_32KHZ; - break; - case XN_SAMPLE_RATE_44K: - *pnDest = A2D_SAMPLE_RATE_44KHZ; - break; - case XN_SAMPLE_RATE_48K: - *pnDest = A2D_SAMPLE_RATE_48KHZ; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::ConvertFirmwareRateToSampleRate(XnUInt64 nSource, XnUInt64* pnDest) -{ - switch (nSource) - { - case A2D_SAMPLE_RATE_8KHZ: - *pnDest = XN_SAMPLE_RATE_8K; - break; - case A2D_SAMPLE_RATE_11KHZ: - *pnDest = XN_SAMPLE_RATE_11K; - break; - case A2D_SAMPLE_RATE_12KHZ: - *pnDest = XN_SAMPLE_RATE_12K; - break; - case A2D_SAMPLE_RATE_16KHZ: - *pnDest = XN_SAMPLE_RATE_16K; - break; - case A2D_SAMPLE_RATE_22KHZ: - *pnDest = XN_SAMPLE_RATE_22K; - break; - case A2D_SAMPLE_RATE_24KHZ: - *pnDest = XN_SAMPLE_RATE_24K; - break; - case A2D_SAMPLE_RATE_32KHZ: - *pnDest = XN_SAMPLE_RATE_32K; - break; - case A2D_SAMPLE_RATE_44KHZ: - *pnDest = XN_SAMPLE_RATE_44K; - break; - case A2D_SAMPLE_RATE_48KHZ: - *pnDest = XN_SAMPLE_RATE_48K; - break; - default: - return XN_STATUS_DEVICE_UNSUPPORTED_MODE; - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::SetLeftChannelVolume(XnUInt32 nVolume) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_LeftChannelVolume, nVolume); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::SetRightChannelVolume(XnUInt32 nVolume) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_RightChannelVolume, nVolume); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorAudioStream::ReallocBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); - - if (m_hSharedMemory == NULL) - { - // first time, create shared memory - - // we allocate enough for 5 seconds of audio - XnUInt32 nSampleSize = 2 * 2; // 16-bit per channel (2 bytes) * max number of channels (2) - XnUInt32 nSamples = 48000 * 5; // max sample rate * number of seconds - - XnUInt32 nMaxBufferSize = nSamples * nSampleSize; - - // find min packet size (so we'll have max packet count) - XnUInt32 nMinPacketSize = XN_MIN(XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK, XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO); - XnUInt32 nMaxPacketCount = nMaxBufferSize / nMinPacketSize - 1; - - XnUInt32 nSharedBufferSize = - sizeof(XnAudioSharedBuffer) + // header - sizeof(XnUInt64) * nMaxPacketCount + // packet timestamps - nMaxBufferSize; - - // to make the name unique, we'll add process ID - XN_PROCESS_ID procID; - xnOSGetCurrentProcessID(&procID); - XnChar strSharedName[XN_DEVICE_MAX_STRING_LENGTH]; - sprintf(strSharedName, "%u_%s", procID, GetName()); - - nRetVal = m_SharedBufferName.UnsafeUpdateValue(strSharedName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RequiredSizeProperty().UnsafeUpdateValue(nMaxBufferSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateSharedMemory(strSharedName, nSharedBufferSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory); - XN_IS_STATUS_OK(nRetVal); - - XnUChar* pAddress; - nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, (void**)&pAddress); - XN_IS_STATUS_OK(nRetVal); - - m_pSharedHeader = (XnAudioSharedBuffer*)pAddress; - pDevicePrivateData->pAudioPacketsTimestamps = (XnUInt64*)(pAddress + sizeof(XnAudioSharedBuffer)); - pDevicePrivateData->pAudioBuffer = (XN_AUDIO_TYPE*)(pAddress + sizeof(XnAudioSharedBuffer) + sizeof(XnUInt64) * nMaxPacketCount); - pDevicePrivateData->nAudioBufferSize = nMaxBufferSize; - - m_pSharedHeader->nTimestampsListOffset = sizeof(XnAudioSharedBuffer); - m_pSharedHeader->nBufferOffset = pDevicePrivateData->pAudioBuffer - pAddress; - } - - // calculate current packet size - pDevicePrivateData->nAudioPacketSize = m_nOrigAudioPacketSize; - - if (m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_2 && GetNumberOfChannels() == 1) - { - pDevicePrivateData->nAudioPacketSize /= 2; - } - - pDevicePrivateData->nAudioBufferNumOfPackets = pDevicePrivateData->nAudioBufferSize / pDevicePrivateData->nAudioPacketSize; - pDevicePrivateData->nAudioBufferSize = pDevicePrivateData->nAudioBufferNumOfPackets * pDevicePrivateData->nAudioPacketSize; - - m_pSharedHeader->nPacketCount = pDevicePrivateData->nAudioBufferNumOfPackets; - m_pSharedHeader->nPacketSize = pDevicePrivateData->nAudioPacketSize; - - // set read and write indices - pDevicePrivateData->nAudioReadIndex = 0; - pDevicePrivateData->nAudioWriteIndex = 0; - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetLeftChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; - return pThis->SetLeftChannelVolume((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetRightChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; - return pThis->SetRightChannelVolume((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; - return pThis->SetActualRead(nValue == TRUE); -} - -XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::NewDataCallback(void* pCookie) -{ - XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; - return pThis->NewData(); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorInit.h" +#include "XnSensorAudioStream.h" +#include "XnSensor.h" +#include "XnAudioProcessor.h" +#include + +#define XN_AUDIO_MAX_SAMPLE_RATE 48000 +#define XN_AUDIO_MAX_NUMBER_OF_CHANNELS 2 + +#define XN_AUDIO_STREAM_DEFAULT_VOLUME 12 +#define XN_AUDIO_STREAM_DEFAULT_SAMPLE_RATE 48000 +#define XN_AUDIO_STREAM_DEFAULT_NUMBER_OF_CHANNELS 2 +#define XN_AUDIO_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_PCM +#define XN_AUDIO_STREAM_DEFAULT_CHUNK_SIZE 2120 + +#define XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK 424 +#define XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO 180 + +XnSensorAudioStream::XnSensorAudioStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects) : + XnAudioStream(StreamName, XN_AUDIO_MAX_NUMBER_OF_CHANNELS), + m_strDeviceName(strDeviceName), + m_Helper(pObjects), + m_LeftChannelVolume(XN_STREAM_PROPERTY_LEFT_CHANNEL_VOLUME, XN_AUDIO_STREAM_DEFAULT_VOLUME), + m_RightChannelVolume(XN_STREAM_PROPERTY_RIGHT_CHANNEL_VOLUME, XN_AUDIO_STREAM_DEFAULT_VOLUME), + m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME), + m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE), + m_hSharedMemory(NULL), + m_pSharedHeader(NULL) +{ + m_LeftChannelVolume.UpdateSetCallback(SetLeftChannelVolumeCallback, this); + m_RightChannelVolume.UpdateSetCallback(SetRightChannelVolumeCallback, this); + m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); +} + +XnStatus XnSensorAudioStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init base + nRetVal = XnAudioStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + // init helper + nRetVal = m_Helper.Init(this, this); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetReadChunkSize(XN_AUDIO_STREAM_DEFAULT_CHUNK_SIZE); + XN_IS_STATUS_OK(nRetVal); + + // add properties + XN_VALIDATE_ADD_PROPERTIES(this, &m_LeftChannelVolume, &m_RightChannelVolume, &m_SharedBufferName, &m_ActualRead); + + // check what's the firmware audio packet size + if (m_Helper.GetPrivateData()->SensorHandle.MiscConnection.bIsISO) + m_nOrigAudioPacketSize = XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO; + else + m_nOrigAudioPacketSize = XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK; + + // alloc buffer + nRetVal = ReallocBuffer(); + XN_IS_STATUS_OK(nRetVal); + + m_Helper.GetPrivateData()->pAudioCallback = NewDataCallback; + m_Helper.GetPrivateData()->pAudioCallbackCookie = this; + + // data processor + nRetVal = m_Helper.RegisterDataProcessorProperty(NumberOfChannelsProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::Free() +{ + m_Helper.Free(); + XnAudioStream::Free(); + if (m_hSharedMemory != NULL) + { + xnOSCloseSharedMemory(m_hSharedMemory); + m_hSharedMemory = NULL; + } + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::MapPropertiesToFirmware() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(SampleRateProperty(), GetFirmwareParams()->m_AudioSampleRate, FALSE, ConvertSampleRateToFirmwareRate)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(NumberOfChannelsProperty(), GetFirmwareParams()->m_AudioStereo, FALSE, ConvertNumberOfChannelsToStereo)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_LeftChannelVolume, GetFirmwareParams()->m_AudioLeftChannelGain, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_RightChannelVolume, GetFirmwareParams()->m_AudioRightChannelGain, TRUE)); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::ConfigureStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp); + + nRetVal = SetActualRead(TRUE); + XN_IS_STATUS_OK(nRetVal); + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(SampleRateProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(NumberOfChannelsProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_LeftChannelVolume)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_RightChannelVolume)); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::SetActualRead(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_ActualRead.GetValue() != bRead) + { + if (bRead) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB audio read thread..."); + nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificMiscUsb->nChunkReadBytes, XN_SENSOR_USB_MISC_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificMiscUsb); + XN_IS_STATUS_OK(nRetVal); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB audio read thread..."); + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificMiscUsb->pUsbConnection->UsbEp); + } + + nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::OpenStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_ON); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnAudioStream::Open(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::CloseStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream2Mode.SetValue(XN_AUDIO_STREAM_OFF); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnAudioStream::Close(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetActualRead(FALSE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::CreateDataProcessor(XnDataProcessor** ppProcessor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDataProcessor* pAudioProcessor; + XN_VALIDATE_NEW_AND_INIT(pAudioProcessor, XnAudioProcessor, this, &m_Helper, m_nOrigAudioPacketSize); + + *ppProcessor = pAudioProcessor; + + return XN_STATUS_OK; +} + +XnStatus XnSensorAudioStream::SetOutputFormat(XnOutputFormats nOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_PCM: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Output format %d, isn't supported by sensor audio stream!", nOutputFormat); + } + + nRetVal = XnAudioStream::SetOutputFormat(nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::SetSampleRate(XnSampleRate nSampleRate) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.BeforeSettingFirmwareParam(SampleRateProperty(), nSampleRate); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnAudioStream::SetSampleRate(nSampleRate); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(SampleRateProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::SetNumberOfChannels(XnUInt32 nNumberOfChannels) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.BeforeSettingFirmwareParam(NumberOfChannelsProperty(), nNumberOfChannels); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnAudioStream::SetNumberOfChannels(nNumberOfChannels); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ReallocBuffer(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(NumberOfChannelsProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::NewData() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); + + // check how many buffers we have + XnInt32 nAvailbalePackets = pDevicePrivateData->nAudioWriteIndex - pDevicePrivateData->nAudioReadIndex; + if (nAvailbalePackets < 0) + nAvailbalePackets += pDevicePrivateData->nAudioBufferNumOfPackets; + + if ((XnUInt32)nAvailbalePackets * pDevicePrivateData->nAudioPacketSize >= GetReadChunkSize()) + { + // update last write index (the last written byte) + m_pSharedHeader->nWritePacketIndex = pDevicePrivateData->nAudioWriteIndex; + // take first packet timestamp + NewDataAvailable(pDevicePrivateData->pAudioPacketsTimestamps[pDevicePrivateData->nAudioReadIndex], 0); + } + + return XN_STATUS_OK; +} + +XnStatus XnSensorAudioStream::ReadImpl(XnStreamData *pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); + + pStreamOutput->nDataSize = 0; + + XN_AUDIO_TYPE* pAudioBuf = (XN_AUDIO_TYPE*)pStreamOutput->pData; + + xnOSEnterCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); + + // check how many buffers we have + XnInt32 nAvailbalePackets = pDevicePrivateData->nAudioWriteIndex - pDevicePrivateData->nAudioReadIndex; + if (nAvailbalePackets < 0) + nAvailbalePackets += pDevicePrivateData->nAudioBufferNumOfPackets; + + // now check if stream frame buffer has enough space + if (GetRequiredDataSize() < (XnUInt32)nAvailbalePackets * pDevicePrivateData->nAudioPacketSize) + { + xnOSLeaveCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); + return (XN_STATUS_IO_INVALID_STREAM_AUDIO_BUFFER_SIZE); + } + + // take first packet timestamp + pStreamOutput->nTimestamp = pDevicePrivateData->pAudioPacketsTimestamps[pDevicePrivateData->nAudioReadIndex]; + XnUChar* pPacketData = pDevicePrivateData->pAudioBuffer + (pDevicePrivateData->nAudioReadIndex * pDevicePrivateData->nAudioPacketSize); + + // copy + while (pDevicePrivateData->nAudioReadIndex != pDevicePrivateData->nAudioWriteIndex) + { + xnOSMemCopy(pAudioBuf, pPacketData, pDevicePrivateData->nAudioPacketSize); + pAudioBuf += pDevicePrivateData->nAudioPacketSize; + pStreamOutput->nDataSize += pDevicePrivateData->nAudioPacketSize; + + pDevicePrivateData->nAudioReadIndex++; + pPacketData += pDevicePrivateData->nAudioPacketSize; + if (pDevicePrivateData->nAudioReadIndex == pDevicePrivateData->nAudioBufferNumOfPackets) + { + pDevicePrivateData->nAudioReadIndex = 0; + pPacketData = pDevicePrivateData->pAudioBuffer; + } + } + + xnOSLeaveCriticalSection(&pDevicePrivateData->hAudioBufferCriticalSection); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::ConvertNumberOfChannelsToStereo(XnUInt64 nSource, XnUInt64* pnDest) +{ + *pnDest = (nSource == 2); + return XN_STATUS_OK; +} + +XnStatus XnSensorAudioStream::ConvertStereoToNumberOfChannels(XnUInt64 nSource, XnUInt64* pnDest) +{ + *pnDest = nSource ? 2 : 1; + return XN_STATUS_OK; +} + +XnStatus XnSensorAudioStream::ConvertSampleRateToFirmwareRate(XnUInt64 nSource, XnUInt64* pnDest) +{ + switch (nSource) + { + case XN_SAMPLE_RATE_8K: + *pnDest = A2D_SAMPLE_RATE_8KHZ; + break; + case XN_SAMPLE_RATE_11K: + *pnDest = A2D_SAMPLE_RATE_11KHZ; + break; + case XN_SAMPLE_RATE_12K: + *pnDest = A2D_SAMPLE_RATE_12KHZ; + break; + case XN_SAMPLE_RATE_16K: + *pnDest = A2D_SAMPLE_RATE_16KHZ; + break; + case XN_SAMPLE_RATE_22K: + *pnDest = A2D_SAMPLE_RATE_22KHZ; + break; + case XN_SAMPLE_RATE_24K: + *pnDest = A2D_SAMPLE_RATE_24KHZ; + break; + case XN_SAMPLE_RATE_32K: + *pnDest = A2D_SAMPLE_RATE_32KHZ; + break; + case XN_SAMPLE_RATE_44K: + *pnDest = A2D_SAMPLE_RATE_44KHZ; + break; + case XN_SAMPLE_RATE_48K: + *pnDest = A2D_SAMPLE_RATE_48KHZ; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::ConvertFirmwareRateToSampleRate(XnUInt64 nSource, XnUInt64* pnDest) +{ + switch (nSource) + { + case A2D_SAMPLE_RATE_8KHZ: + *pnDest = XN_SAMPLE_RATE_8K; + break; + case A2D_SAMPLE_RATE_11KHZ: + *pnDest = XN_SAMPLE_RATE_11K; + break; + case A2D_SAMPLE_RATE_12KHZ: + *pnDest = XN_SAMPLE_RATE_12K; + break; + case A2D_SAMPLE_RATE_16KHZ: + *pnDest = XN_SAMPLE_RATE_16K; + break; + case A2D_SAMPLE_RATE_22KHZ: + *pnDest = XN_SAMPLE_RATE_22K; + break; + case A2D_SAMPLE_RATE_24KHZ: + *pnDest = XN_SAMPLE_RATE_24K; + break; + case A2D_SAMPLE_RATE_32KHZ: + *pnDest = XN_SAMPLE_RATE_32K; + break; + case A2D_SAMPLE_RATE_44KHZ: + *pnDest = XN_SAMPLE_RATE_44K; + break; + case A2D_SAMPLE_RATE_48KHZ: + *pnDest = XN_SAMPLE_RATE_48K; + break; + default: + return XN_STATUS_DEVICE_UNSUPPORTED_MODE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::SetLeftChannelVolume(XnUInt32 nVolume) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_LeftChannelVolume, nVolume); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::SetRightChannelVolume(XnUInt32 nVolume) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_RightChannelVolume, nVolume); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorAudioStream::ReallocBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData(); + + if (m_hSharedMemory == NULL) + { + // first time, create shared memory + + // we allocate enough for 5 seconds of audio + XnUInt32 nSampleSize = 2 * 2; // 16-bit per channel (2 bytes) * max number of channels (2) + XnUInt32 nSamples = 48000 * 5; // max sample rate * number of seconds + + XnUInt32 nMaxBufferSize = nSamples * nSampleSize; + + // find min packet size (so we'll have max packet count) + XnUInt32 nMinPacketSize = XN_MIN(XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK, XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO); + XnUInt32 nMaxPacketCount = nMaxBufferSize / nMinPacketSize - 1; + + XnUInt32 nSharedBufferSize = + sizeof(XnAudioSharedBuffer) + // header + sizeof(XnUInt64) * nMaxPacketCount + // packet timestamps + nMaxBufferSize; + + // to make the name unique, we'll add process ID + XN_PROCESS_ID procID; + xnOSGetCurrentProcessID(&procID); + XnChar strSharedName[XN_DEVICE_MAX_STRING_LENGTH]; + sprintf(strSharedName, "%u_%s_%s", procID, m_strDeviceName, GetName()); + + nRetVal = m_SharedBufferName.UnsafeUpdateValue(strSharedName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RequiredSizeProperty().UnsafeUpdateValue(nMaxBufferSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateSharedMemory(strSharedName, nSharedBufferSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory); + XN_IS_STATUS_OK(nRetVal); + + XnUChar* pAddress; + nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, (void**)&pAddress); + XN_IS_STATUS_OK(nRetVal); + + m_pSharedHeader = (XnAudioSharedBuffer*)pAddress; + pDevicePrivateData->pAudioPacketsTimestamps = (XnUInt64*)(pAddress + sizeof(XnAudioSharedBuffer)); + pDevicePrivateData->pAudioBuffer = (XN_AUDIO_TYPE*)(pAddress + sizeof(XnAudioSharedBuffer) + sizeof(XnUInt64) * nMaxPacketCount); + pDevicePrivateData->nAudioBufferSize = nMaxBufferSize; + + m_pSharedHeader->nTimestampsListOffset = sizeof(XnAudioSharedBuffer); + m_pSharedHeader->nBufferOffset = pDevicePrivateData->pAudioBuffer - pAddress; + } + + // calculate current packet size + pDevicePrivateData->nAudioPacketSize = m_nOrigAudioPacketSize; + + if (m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_2 && GetNumberOfChannels() == 1) + { + pDevicePrivateData->nAudioPacketSize /= 2; + } + + pDevicePrivateData->nAudioBufferNumOfPackets = pDevicePrivateData->nAudioBufferSize / pDevicePrivateData->nAudioPacketSize; + pDevicePrivateData->nAudioBufferSize = pDevicePrivateData->nAudioBufferNumOfPackets * pDevicePrivateData->nAudioPacketSize; + + m_pSharedHeader->nPacketCount = pDevicePrivateData->nAudioBufferNumOfPackets; + m_pSharedHeader->nPacketSize = pDevicePrivateData->nAudioPacketSize; + + // set read and write indices + pDevicePrivateData->nAudioReadIndex = 0; + pDevicePrivateData->nAudioWriteIndex = 0; + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetLeftChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; + return pThis->SetLeftChannelVolume((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetRightChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; + return pThis->SetRightChannelVolume((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; + return pThis->SetActualRead(nValue == TRUE); +} + +XnStatus XN_CALLBACK_TYPE XnSensorAudioStream::NewDataCallback(void* pCookie) +{ + XnSensorAudioStream* pThis = (XnSensorAudioStream*)pCookie; + return pThis->NewData(); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorAudioStream.h b/Source/XnDeviceSensorV2/XnSensorAudioStream.h index 0b4e1de..5a4bdab 100644 --- a/Source/XnDeviceSensorV2/XnSensorAudioStream.h +++ b/Source/XnDeviceSensorV2/XnSensorAudioStream.h @@ -1,117 +1,118 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_AUDIO_STREAM_H__ -#define __XN_SENSOR_AUDIO_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensorStreamHelper.h" -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// XnSensorAudioStream class -//--------------------------------------------------------------------------- -class XnSensorAudioStream : public XnAudioStream, public IXnSensorStream -{ -public: - XnSensorAudioStream(const XnChar* StreamName, XnSensorObjects* pObjects); - ~XnSensorAudioStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } - - inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } - - friend class XnAudioProcessor; -protected: - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Open() { return m_Helper.Open(); } - XnStatus Close() { return m_Helper.Close(); } - XnStatus ConfigureStreamImpl(); - XnStatus OpenStreamImpl(); - XnStatus CloseStreamImpl(); - XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); - XnStatus MapPropertiesToFirmware(); - void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = XN_RESOLUTION_CUSTOM; *pnFPS = 0; } - XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return NULL; } - - XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } - XnStatus ReadImpl(XnStreamData* pStreamOutput); - XnStatus Mirror(XnStreamData* pStreamOutput) const { return XN_STATUS_OK; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); - XnStatus SetLeftChannelVolume(XnUInt32 nVolume); - XnStatus SetRightChannelVolume(XnUInt32 nVolume); - XnStatus SetSampleRate(XnSampleRate nSampleRate); - XnStatus SetNumberOfChannels(XnUInt32 nNumberOfChannels); - XnStatus SetActualRead(XnBool bRead); - -private: - XnStatus NewData(); - XnStatus ReallocBuffer(); - - inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } - - static XnStatus ConvertNumberOfChannelsToStereo(XnUInt64 nSource, XnUInt64* pnDest); - static XnStatus ConvertStereoToNumberOfChannels(XnUInt64 nSource, XnUInt64* pnDest); - static XnStatus ConvertSampleRateToFirmwareRate(XnUInt64 nSource, XnUInt64* pnDest); - static XnStatus ConvertFirmwareRateToSampleRate(XnUInt64 nSource, XnUInt64* pnDest); - - static XnStatus XN_CALLBACK_TYPE SetLeftChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetRightChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE NewDataCallback(void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnSensorStreamHelper m_Helper; - - XnActualStringProperty m_SharedBufferName; - XnActualIntProperty m_LeftChannelVolume; - XnActualIntProperty m_RightChannelVolume; - - XnActualIntProperty m_ActualRead; - - XnUInt32 m_nOrigAudioPacketSize; - - XN_SHARED_MEMORY_HANDLE m_hSharedMemory; - XnAudioSharedBuffer* m_pSharedHeader; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_AUDIO_STREAM_H__ +#define __XN_SENSOR_AUDIO_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensorStreamHelper.h" +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// XnSensorAudioStream class +//--------------------------------------------------------------------------- +class XnSensorAudioStream : public XnAudioStream, public IXnSensorStream +{ +public: + XnSensorAudioStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects); + ~XnSensorAudioStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } + + inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } + + friend class XnAudioProcessor; +protected: + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Open() { return m_Helper.Open(); } + XnStatus Close() { return m_Helper.Close(); } + XnStatus ConfigureStreamImpl(); + XnStatus OpenStreamImpl(); + XnStatus CloseStreamImpl(); + XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); + XnStatus MapPropertiesToFirmware(); + void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = XN_RESOLUTION_CUSTOM; *pnFPS = 0; } + XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return NULL; } + + XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } + XnStatus ReadImpl(XnStreamData* pStreamOutput); + XnStatus Mirror(XnStreamData* pStreamOutput) const { return XN_STATUS_OK; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); + XnStatus SetLeftChannelVolume(XnUInt32 nVolume); + XnStatus SetRightChannelVolume(XnUInt32 nVolume); + XnStatus SetSampleRate(XnSampleRate nSampleRate); + XnStatus SetNumberOfChannels(XnUInt32 nNumberOfChannels); + XnStatus SetActualRead(XnBool bRead); + +private: + XnStatus NewData(); + XnStatus ReallocBuffer(); + + inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } + + static XnStatus ConvertNumberOfChannelsToStereo(XnUInt64 nSource, XnUInt64* pnDest); + static XnStatus ConvertStereoToNumberOfChannels(XnUInt64 nSource, XnUInt64* pnDest); + static XnStatus ConvertSampleRateToFirmwareRate(XnUInt64 nSource, XnUInt64* pnDest); + static XnStatus ConvertFirmwareRateToSampleRate(XnUInt64 nSource, XnUInt64* pnDest); + + static XnStatus XN_CALLBACK_TYPE SetLeftChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetRightChannelVolumeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE NewDataCallback(void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnSensorStreamHelper m_Helper; + + const XnChar* m_strDeviceName; + XnActualStringProperty m_SharedBufferName; + XnActualIntProperty m_LeftChannelVolume; + XnActualIntProperty m_RightChannelVolume; + + XnActualIntProperty m_ActualRead; + + XnUInt32 m_nOrigAudioPacketSize; + + XN_SHARED_MEMORY_HANDLE m_hSharedMemory; + XnAudioSharedBuffer* m_pSharedHeader; +}; + #endif //__XN_SENSOR_AUDIO_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorClient.cpp b/Source/XnDeviceSensorV2/XnSensorClient.cpp index 8bb6320..1a56795 100644 --- a/Source/XnDeviceSensorV2/XnSensorClient.cpp +++ b/Source/XnDeviceSensorV2/XnSensorClient.cpp @@ -1,899 +1,899 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorClient.h" -#include "XnSensor.h" -#include "XnSensorClientServer.h" -#include -#include "XnSensorClientStream.h" -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -//#define XN_SENSOR_CLIENT_WAIT_FOR_SERVER 10000 -#define XN_SENSOR_CLIENT_WAIT_FOR_SERVER 5000 -#define XN_SENSOR_CLIENT_READ_TIMEOUT 4000 -#define XN_SENSOR_CLIENT_TERMINATE_THREAD_TIMEOUT (XN_SENSOR_CLIENT_READ_TIMEOUT * 2) -#define XN_SENSOR_CLIENT_CONNECT_RETRIES 2 -#define XN_MASK_SENSOR_CLIENT "SensorClient" - -//--------------------------------------------------------------------------- -// XnSensorClient class -//--------------------------------------------------------------------------- -XnChar XnSensorClient::ms_strDir[XN_FILE_MAX_PATH]; - -XnStatus XnSensorClient::TakeServerLocation() -{ - return xnOSGetCurrentDir(ms_strDir, XN_FILE_MAX_PATH); -} - -XnSensorClient::XnSensorClient() : - XnStreamReaderDevice(XN_DEVICE_NAME, XN_SENSOR_SERVER_MAX_MESSAGE_SIZE), - m_hSocket(NULL), - m_hReplyEvent(NULL), - m_hListenThread(NULL), - m_pOutgoingPacker(NULL), - m_bShouldRun(TRUE), - m_bConnected(TRUE), - m_pThis(this), - m_InstancePointer(XN_SENSOR_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL), - m_ErrorState(XN_MODULE_PROPERTY_ERROR_STATE, XN_STATUS_OK), - m_hLock(NULL) -{ - strcpy(m_strConfigDir, "."); -} - -XnSensorClient::~XnSensorClient() -{ -} - -void XnSensorClient::SetConfigDir(const XnChar* strConfigDir) -{ - strcpy(m_strConfigDir, strConfigDir); -} - -XnStatus XnSensorClient::GetDefinition(XnDeviceDefinition* pDeviceDefinition) -{ - return XnSensor::GetDefinition(pDeviceDefinition); -} - -XnStatus XnSensorClient::Enumerate(XnConnectionString *aConnectionStrings, XnUInt32 *pnCount) -{ - return XnSensor::Enumerate(aConnectionStrings, pnCount); -} - -XnStatus XnSensorClient::Init(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamReaderDevice::Init(pDeviceConfig); - XN_IS_STATUS_OK(nRetVal); - - m_pThis = this; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::InitImpl(const XnDeviceConfig* pDeviceConfig) -{ - XnStatus nRetVal = XN_STATUS_OK; - XN_MUTEX_HANDLE hServerRunningMutex = NULL; - XnOSEvent serverRunningEvent; - - nRetVal = serverRunningEvent.Open(XN_SENSOR_SERVER_RUNNING_EVENT_NAME); - if (nRetVal != XN_STATUS_OK) - { - nRetVal = serverRunningEvent.Create(XN_SENSOR_SERVER_RUNNING_EVENT_NAME, TRUE); - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to create server running event: %s", xnGetStatusString(nRetVal)); - return nRetVal; - } - } - - nRetVal = xnOSCreateNamedMutex(&hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_NAME); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSLockMutex(hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); - if (nRetVal != XN_STATUS_OK) - { - xnOSCloseMutex(&hServerRunningMutex); - return nRetVal; - } - - XnBool bServerRunning = (serverRunningEvent.Wait(1) == XN_STATUS_OK); - nRetVal = xnOSUnLockMutex(hServerRunningMutex); - xnOSCloseMutex(&hServerRunningMutex); - XN_IS_STATUS_OK(nRetVal); - - if (!bServerRunning) - { - nRetVal = StartServerProcess(); - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to start server process: %s", xnGetStatusString(nRetVal)); - return nRetVal; - } - } - - nRetVal = serverRunningEvent.Wait(XN_SENSOR_CLIENT_WAIT_FOR_SERVER); - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to wait for server to start: %s", xnGetStatusString(nRetVal)); - return nRetVal; - } - - // init network - nRetVal = xnOSInitNetwork(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateCriticalSection(&m_hLock); - XN_IS_STATUS_OK(nRetVal); - - // now init - nRetVal = XnStreamReaderDevice::InitImpl(pDeviceConfig); - if (nRetVal != XN_STATUS_OK) - { - xnOSCloseCriticalSection(&m_hLock); - return nRetVal; - } - - m_bConnected = TRUE; - - nRetVal = xnOSCreateEvent(&m_hReplyEvent, FALSE); - if (nRetVal != XN_STATUS_OK) - { - xnOSCloseCriticalSection(&m_hLock); - return nRetVal; - } - - nRetVal = xnOSCreateThread(ListenThread, this, &m_hListenThread); - if (nRetVal != XN_STATUS_OK) - { - xnOSCloseEvent(&m_hReplyEvent); - xnOSCloseCriticalSection(&m_hLock); - return nRetVal; - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::ReadInitialState(XnPropertySet* pSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // first message should be either the initial state or an error message (if server failed to open - // sensor) - XnPackedDataType nType; - nRetVal = GetDataPacker()->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - if (nType == XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND) - { - // check the error code - XnUInt32 nDataSize = sizeof(m_LastReply); - nRetVal = GetDataPacker()->ReadCustomData(nType, &m_LastReply, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - XN_LOG_WARNING_RETURN(m_LastReply.nRetVal, XN_MASK_SENSOR_SERVER, "Server returned an error: %s", xnGetStatusString(m_LastReply.nRetVal)); - } - else if (nType == XN_PACKED_PROPERTY_SET) - { - nRetVal = GetDataPacker()->ReadPropertySet(pSet); - XN_IS_STATUS_OK(nRetVal); - } - else - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR, XN_MASK_DDK, "Unexpected message: %d (should start with a GENERAL_OP_RESPOND or PROPERTY_SET)", nType); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::Destroy() -{ - XnStatus nRetVal = XN_STATUS_OK; - if (m_hSocket != NULL) - { - nRetVal = SendBye(); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_CLIENT, "Failed to send BYE to the server - %s", xnGetStatusString(nRetVal)); - //But we keep going - we must destroy our object. - } - - //Signal to the listener thread that it should stop running - m_bShouldRun = FALSE; - m_bConnected = FALSE; - } - - if (m_hListenThread != NULL) - { - xnOSWaitAndTerminateThread(&m_hListenThread, XN_SENSOR_CLIENT_TERMINATE_THREAD_TIMEOUT); - m_hListenThread = NULL; - } - - // now destroy it all - XnStreamReaderDevice::Destroy(); - - if (m_hReplyEvent != NULL) - { - xnOSCloseEvent(&m_hReplyEvent); - m_hReplyEvent = NULL; - } - - XN_DELETE(m_pOutgoingPacker); - - if (m_hLock != NULL) - { - xnOSCloseCriticalSection(&m_hLock); - m_hLock = NULL; - } - - return XN_STATUS_OK; -} - -XnStatus XnSensorClient::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_PROPERTY_SET_CREATE_ON_STACK(props); - if (pInitialValues == NULL) - { - pInitialValues = &props; - } - - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Creating stream %s (of type %s)", StreamName, StreamType); - - nRetVal = m_pOutgoingPacker->WriteNewStream(StreamType, StreamName, pInitialValues); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::DestroyStream(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Destroying stream %s", StreamName); - - // this might be called after connection was closed - if (m_bConnected) - { - nRetVal = m_pOutgoingPacker->WriteStreamRemoved(StreamName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - } - - XnStreamReaderDevice::DestroyStream(StreamName); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if we have a local copy - nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, pnValue); - if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) - { - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); - - // get from server (virtual property?) - XnSensorServerMessageGetPropertyRequest request; - strcpy(request.strModuleName, ModuleName); - strcpy(request.strPropertyName, PropertyName); - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, &request, sizeof(request)); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY); - XN_IS_STATUS_OK(nRetVal); - - *pnValue = *(XnUInt64*)m_LastReply.pData; - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if we have a local copy - nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, pdValue); - if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) - { - // get from server (virtual property?) - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); - XnSensorServerMessageGetPropertyRequest request; - strcpy(request.strModuleName, ModuleName); - strcpy(request.strPropertyName, PropertyName); - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, &request, sizeof(request)); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY); - XN_IS_STATUS_OK(nRetVal); - - *pdValue = *(XnDouble*)m_LastReply.pData; - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if we have a local copy - nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, strValue); - if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) - { - // get from server (virtual property?) - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); - XnSensorServerMessageGetPropertyRequest request; - strcpy(request.strModuleName, ModuleName); - strcpy(request.strPropertyName, PropertyName); - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, &request, sizeof(request)); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY); - XN_IS_STATUS_OK(nRetVal); - - strcpy(strValue, (const XnChar*)m_LastReply.pData); - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if we have a local copy - nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, Value); - if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) - { - // get from server (virtual property?) - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); - XnUInt32 nBufSize = sizeof(XnSensorServerMessageGetPropertyRequest) + Value.nDataSize; - XnUChar bufValue[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; - XnUChar* pBuf = bufValue; - - XnSensorServerMessageGetPropertyRequest* pRequest = (XnSensorServerMessageGetPropertyRequest*)pBuf; - XnUChar* pData = pBuf + sizeof(XnSensorServerMessageGetPropertyRequest); - - strcpy(pRequest->strModuleName, ModuleName); - strcpy(pRequest->strPropertyName, PropertyName); - pRequest->nSize = Value.nDataSize; - - // copy data - xnOSMemCopy(pData, Value.pData, Value.nDataSize); - - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, pBuf, nBufSize); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY); - XN_IS_STATUS_OK(nRetVal); - - xnOSMemCopy(Value.pData, m_LastReply.pData, m_LastReply.nDataSize); - } - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // there are some properties we don't change on the server (they affect only this client) - if (strcmp(ModuleName, XN_MODULE_NAME_DEVICE) == 0 && strcmp(PropertyName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) - { - nRetVal = XnStreamReaderDevice::SetProperty(ModuleName, PropertyName, nValue); - XN_IS_STATUS_OK(nRetVal); - } - else - { - // set it on the server - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %llu...", ModuleName, PropertyName, nValue); - - nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %f...", ModuleName, PropertyName, dValue); - - nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, dValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %s...", ModuleName, PropertyName, strValue); - - nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, strValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s...", ModuleName, PropertyName); - - nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, Value); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::BatchConfig(const XnPropertySet* pChangeSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Batch configuring server..."); - - nRetVal = m_pOutgoingPacker->WritePropertySet(pChangeSet); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::ReadStream(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bConnected) - { - return (XN_STATUS_DEVICE_SERVER_DISCONNECTED); - } - - nRetVal = XnStreamReaderDevice::ReadStream(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::Read(XnStreamDataSet* pStreamOutputSet) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bConnected) - { - return (XN_STATUS_DEVICE_SERVER_DISCONNECTED); - } - - nRetVal = XnStreamReaderDevice::Read(pStreamOutputSet); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::SendBye() -{ - xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Sending Bye"); - XnStatus nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_BYE, NULL, 0); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_BYE); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_OK; -} - -XnStatus XnSensorClient::HandlePackedObject(XnPackedDataType nObjectType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nDataSize = sizeof(m_LastReply); - - switch (nObjectType) - { - case XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND: - case XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY: - case XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY: - case XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY: - case XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY: - case XN_SENSOR_SERVER_MESSAGE_READ_STREAM: - case XN_SENSOR_SERVER_MESSAGE_BYE: - { - nRetVal = GetDataPacker()->ReadCustomData(nObjectType, &m_LastReply, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSSetEvent(m_hReplyEvent); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA: - { - XnSensorServerNewStreamData message; - XnUInt32 nDataSize = sizeof(message); - nRetVal = GetDataPacker()->ReadCustomData(nObjectType, &message, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - // find the stream - XnStreamDeviceStreamHolder* pHolder = NULL; - nRetVal = FindStream(message.strStreamName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - pHolder->GetStream()->NewDataAvailable(message.nTimestamp, message.nFrameID); - break; - } - default: - { - nRetVal = XnStreamReaderDevice::HandlePackedObject(nObjectType); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamReaderDevice::HandleNewStream(strType, strName, pInitialValues); - XN_IS_STATUS_OK(nRetVal); - - // open shared memory - XnStreamDeviceStreamHolder* pHolder = NULL; - nRetVal = FindStream(strName, &pHolder); - XN_IS_STATUS_OK(nRetVal); - - XnSensorClientStream* pStream = (XnSensorClientStream*)pHolder->GetStream(); - nRetVal = pStream->OpenSharedMemory(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // ignore some properties - if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_SENSOR_PROPERTY_INSTANCE_POINTER) == 0) - { - return (XN_STATUS_OK); - } - else - { - nRetVal = XnStreamReaderDevice::HandleGeneralProperty(strModule, strName, gbValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::WaitForReply(XnSensorServerCustomMessages ExpectedMessage) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // wait for event - nRetVal = xnOSWaitEvent(m_hReplyEvent, XN_SENSOR_REPLY_TIMEOUT); - if (nRetVal != XN_STATUS_OK) - { - XN_LOG_WARNING_RETURN(nRetVal, XN_MASK_SENSOR_SERVER, "Timeout when waiting for reply from sensor server!"); - } - - // reset it - nRetVal = xnOSResetEvent(m_hReplyEvent); - XN_IS_STATUS_OK(nRetVal); - - // check error code - if (m_LastReply.nRetVal != XN_STATUS_OK) - { - XN_LOG_WARNING_RETURN(m_LastReply.nRetVal, XN_MASK_SENSOR_SERVER, "Server returned an error: %s", xnGetStatusString(m_LastReply.nRetVal)); - } - - if (m_LastReply.Type != ExpectedMessage) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid reply type!"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnSensorServerMessageIniFile message; - strncpy(message.strFileName, csINIFilePath, XN_FILE_MAX_PATH); - strncpy(message.strSectionName, csSectionName, XN_DEVICE_MAX_STRING_LENGTH); - - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_INI_FILE, &message, sizeof(message)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::CreateIOStreamImpl(const XnChar *strConnectionString, XnIOStream *&pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = xnOSCreateSocket(XN_OS_TCP_SOCKET, XN_SENSOR_SERVER_IP_ADDRESS, XN_SENSOR_SERVER_PORT, &m_hSocket); - XN_IS_STATUS_OK(nRetVal); - - // connect to server - XnUInt64 nStart; - xnOSGetTimeStamp(&nStart); - - nRetVal = XN_STATUS_OS_NETWORK_TIMEOUT; - for (XnUInt32 nRetries = 0; (nRetries < XN_SENSOR_CLIENT_CONNECT_RETRIES) && (nRetVal != XN_STATUS_OK); nRetries++) - { - nRetVal = xnOSConnectSocket(m_hSocket, XN_SENSOR_CLIENT_WAIT_FOR_SERVER); - } - - if (nRetVal == XN_STATUS_OS_NETWORK_TIMEOUT) - { - xnLogError(XN_MASK_SENSOR_CLIENT, "Got timeout waiting for server"); - return nRetVal; - } - else if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_CLIENT, "Got an error trying to connect to server socket: %s", xnGetStatusString(nRetVal)); - return nRetVal; - } - - XnIONetworkStream *pNetworkStream = XN_NEW(XnIONetworkStream, m_hSocket); - if (pNetworkStream == NULL) - { - xnOSCloseSocket(m_hSocket); - return XN_STATUS_ALLOC_FAILED; - } - pNetworkStream->SetReadTimeout(XN_SENSOR_CLIENT_READ_TIMEOUT); - pStream = pNetworkStream; - - // create outgoing data packer (incoming is created by base class) - m_pOutgoingPacker = XN_NEW(XnDataPacker, pNetworkStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE); - if (m_pOutgoingPacker == NULL) - { - XN_DELETE(pNetworkStream); - xnOSCloseSocket(m_hSocket); - return XN_STATUS_ALLOC_FAILED; - } - - nRetVal = m_pOutgoingPacker->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pNetworkStream); - XN_DELETE(m_pOutgoingPacker); - xnOSCloseSocket(m_hSocket); - return nRetVal; - } - - // send server a request to open the sensor - nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, strConnectionString, strlen(strConnectionString) + 1); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pNetworkStream); - XN_DELETE(m_pOutgoingPacker); - xnOSCloseSocket(m_hSocket); - return nRetVal; - } - - return (XN_STATUS_OK); -} - -void XnSensorClient::DestroyIOStreamImpl(XnIOStream* pStream) -{ - XN_DELETE(pStream); - if (m_hSocket != NULL) - { - xnOSCloseSocket(m_hSocket); - m_hSocket = NULL; - } -} - -XnStatus XnSensorClient::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDeviceBase::CreateDeviceModule(ppModuleHolder); - XN_IS_STATUS_OK(nRetVal); - - // add sensor properties - XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); - XnProperty* pProps[] = { &m_InstancePointer, &m_ErrorState }; - - nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); - if (nRetVal != XN_STATUS_OK) - { - DestroyModule(*ppModuleHolder); - *ppModuleHolder = NULL; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClient::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnSensorClientStream* pStream; - if (strcmp(StreamType, XN_STREAM_TYPE_AUDIO) == 0) - { - XN_VALIDATE_NEW(pStream, XnSensorClientAudioStream, this, StreamType, StreamName); - } - else - { - XN_VALIDATE_NEW(pStream, XnSensorClientFrameStream, this, StreamType, StreamName); - } - - XnStreamReaderStreamHolder* pHolder = XN_NEW(XnStreamReaderStreamHolder, pStream); - if (pHolder == NULL) - { - XN_DELETE(pStream); - return XN_STATUS_ALLOC_FAILED; - } - - *ppStreamHolder = pHolder; - - return (XN_STATUS_OK); -} - -void XnSensorClient::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) -{ - XN_DELETE(pStreamHolder->GetModule()); - XN_DELETE(pStreamHolder); -} - -XnStatus XnSensorClient::Listen() -{ - XnStatus nRetVal = XN_STATUS_OK; - - while (m_bShouldRun) - { - nRetVal = ReadNextEventFromStream(); - if (nRetVal == XN_STATUS_OS_NETWORK_TIMEOUT) - { - continue; - } - else if ((nRetVal == XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) && !m_bShouldRun) - { - xnLogInfo(XN_MASK_SENSOR_CLIENT, "Client connection was closed gracefully"); - } - else if (nRetVal != XN_STATUS_OK) - { - XnIONetworkStream* pStream = (XnIONetworkStream*)GetIOStream(); - if (!pStream->IsConnected()) - { - m_bConnected = FALSE; - xnLogError(XN_MASK_SENSOR_CLIENT, "Server has disconnected!"); - break; - } - else - { - xnLogWarning(XN_MASK_SENSOR_CLIENT, "Sensor client failed to handle event: %s", xnGetStatusString(nRetVal)); - } - } - } - - return (XN_STATUS_OK); -} - -XN_THREAD_PROC XnSensorClient::ListenThread(XN_THREAD_PARAM pThreadParam) -{ - XnSensorClient* pThis = (XnSensorClient*)pThreadParam; - XnStatus nRetVal = pThis->Listen(); - XN_THREAD_PROC_RETURN(nRetVal); -} - -XnStatus XnSensorClient::StartServerProcess() -{ - XnStatus nRetVal = XN_STATUS_OK; - - const XnChar* strServerDir; - -#if (XN_PLATFORM == XN_PLATFORM_WIN32) - strServerDir = ms_strDir; -#elif (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM) - strServerDir = "/usr/bin"; -#endif - - // we'll start it in it's directory - XnChar strCurrDir[XN_FILE_MAX_PATH]; - nRetVal = xnOSGetCurrentDir(strCurrDir, XN_FILE_MAX_PATH); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSSetCurrentDir(strServerDir); - XN_IS_STATUS_OK(nRetVal); - - XnChar strProcessName[XN_FILE_MAX_PATH]; - sprintf(strProcessName, "%s%sXnSensorServer", strServerDir, XN_FILE_DIR_SEP); - -#if (XN_PLATFORM == XN_PLATFORM_WIN32) - XN_VALIDATE_STR_APPEND(strProcessName, ".exe", XN_FILE_MAX_PATH, nRetVal); -#endif - - const XnChar* strArguments[] = { m_strConfigDir }; - - XN_PROCESS_ID procID; - nRetVal = xnOSCreateProcess(strProcessName, 1, strArguments, &procID); - - // in any case, return to working dir - xnOSSetCurrentDir(strCurrDir); - - // now check for errors - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorClient.h" +#include "XnSensor.h" +#include "XnSensorClientServer.h" +#include +#include "XnSensorClientStream.h" +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +//#define XN_SENSOR_CLIENT_WAIT_FOR_SERVER 10000 +#define XN_SENSOR_CLIENT_WAIT_FOR_SERVER 5000 +#define XN_SENSOR_CLIENT_READ_TIMEOUT 4000 +#define XN_SENSOR_CLIENT_TERMINATE_THREAD_TIMEOUT (XN_SENSOR_CLIENT_READ_TIMEOUT * 2) +#define XN_SENSOR_CLIENT_CONNECT_RETRIES 2 +#define XN_MASK_SENSOR_CLIENT "SensorClient" + +//--------------------------------------------------------------------------- +// XnSensorClient class +//--------------------------------------------------------------------------- +XnChar XnSensorClient::ms_strDir[XN_FILE_MAX_PATH]; + +XnStatus XnSensorClient::TakeServerLocation() +{ + return xnOSGetCurrentDir(ms_strDir, XN_FILE_MAX_PATH); +} + +XnSensorClient::XnSensorClient() : + XnStreamReaderDevice(XN_DEVICE_NAME, XN_SENSOR_SERVER_MAX_MESSAGE_SIZE), + m_hSocket(NULL), + m_hReplyEvent(NULL), + m_hListenThread(NULL), + m_pOutgoingPacker(NULL), + m_bShouldRun(TRUE), + m_bConnected(TRUE), + m_pThis(this), + m_InstancePointer(XN_SENSOR_PROPERTY_INSTANCE_POINTER, &m_pThis, sizeof(m_pThis), NULL), + m_ErrorState(XN_MODULE_PROPERTY_ERROR_STATE, XN_STATUS_OK), + m_hLock(NULL) +{ + strcpy(m_strConfigDir, "."); +} + +XnSensorClient::~XnSensorClient() +{ +} + +void XnSensorClient::SetConfigDir(const XnChar* strConfigDir) +{ + strcpy(m_strConfigDir, strConfigDir); +} + +XnStatus XnSensorClient::GetDefinition(XnDeviceDefinition* pDeviceDefinition) +{ + return XnSensor::GetDefinition(pDeviceDefinition); +} + +XnStatus XnSensorClient::Enumerate(XnConnectionString *aConnectionStrings, XnUInt32 *pnCount) +{ + return XnSensor::Enumerate(aConnectionStrings, pnCount); +} + +XnStatus XnSensorClient::Init(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamReaderDevice::Init(pDeviceConfig); + XN_IS_STATUS_OK(nRetVal); + + m_pThis = this; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::InitImpl(const XnDeviceConfig* pDeviceConfig) +{ + XnStatus nRetVal = XN_STATUS_OK; + XN_MUTEX_HANDLE hServerRunningMutex = NULL; + XnOSEvent serverRunningEvent; + + nRetVal = serverRunningEvent.Open(XN_SENSOR_SERVER_RUNNING_EVENT_NAME); + if (nRetVal != XN_STATUS_OK) + { + nRetVal = serverRunningEvent.Create(XN_SENSOR_SERVER_RUNNING_EVENT_NAME, TRUE); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to create server running event: %s", xnGetStatusString(nRetVal)); + return nRetVal; + } + } + + nRetVal = xnOSCreateNamedMutex(&hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_NAME); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSLockMutex(hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); + if (nRetVal != XN_STATUS_OK) + { + xnOSCloseMutex(&hServerRunningMutex); + return nRetVal; + } + + XnBool bServerRunning = (serverRunningEvent.Wait(1) == XN_STATUS_OK); + nRetVal = xnOSUnLockMutex(hServerRunningMutex); + xnOSCloseMutex(&hServerRunningMutex); + XN_IS_STATUS_OK(nRetVal); + + if (!bServerRunning) + { + nRetVal = StartServerProcess(); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to start server process: %s", xnGetStatusString(nRetVal)); + return nRetVal; + } + } + + nRetVal = serverRunningEvent.Wait(XN_SENSOR_CLIENT_WAIT_FOR_SERVER); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_CLIENT, "Failed to wait for server to start: %s", xnGetStatusString(nRetVal)); + return nRetVal; + } + + // init network + nRetVal = xnOSInitNetwork(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + // now init + nRetVal = XnStreamReaderDevice::InitImpl(pDeviceConfig); + if (nRetVal != XN_STATUS_OK) + { + xnOSCloseCriticalSection(&m_hLock); + return nRetVal; + } + + m_bConnected = TRUE; + + nRetVal = xnOSCreateEvent(&m_hReplyEvent, FALSE); + if (nRetVal != XN_STATUS_OK) + { + xnOSCloseCriticalSection(&m_hLock); + return nRetVal; + } + + nRetVal = xnOSCreateThread(ListenThread, this, &m_hListenThread); + if (nRetVal != XN_STATUS_OK) + { + xnOSCloseEvent(&m_hReplyEvent); + xnOSCloseCriticalSection(&m_hLock); + return nRetVal; + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::ReadInitialState(XnPropertySet* pSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // first message should be either the initial state or an error message (if server failed to open + // sensor) + XnPackedDataType nType; + nRetVal = GetDataPacker()->ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + if (nType == XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND) + { + // check the error code + XnUInt32 nDataSize = sizeof(m_LastReply); + nRetVal = GetDataPacker()->ReadCustomData(nType, &m_LastReply, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + XN_LOG_WARNING_RETURN(m_LastReply.nRetVal, XN_MASK_SENSOR_SERVER, "Server returned an error: %s", xnGetStatusString(m_LastReply.nRetVal)); + } + else if (nType == XN_PACKED_PROPERTY_SET) + { + nRetVal = GetDataPacker()->ReadPropertySet(pSet); + XN_IS_STATUS_OK(nRetVal); + } + else + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_PROTOCOL_UNKNOWN_ERROR, XN_MASK_DDK, "Unexpected message: %d (should start with a GENERAL_OP_RESPOND or PROPERTY_SET)", nType); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::Destroy() +{ + XnStatus nRetVal = XN_STATUS_OK; + if (m_hSocket != NULL) + { + nRetVal = SendBye(); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_CLIENT, "Failed to send BYE to the server - %s", xnGetStatusString(nRetVal)); + //But we keep going - we must destroy our object. + } + + //Signal to the listener thread that it should stop running + m_bShouldRun = FALSE; + m_bConnected = FALSE; + } + + if (m_hListenThread != NULL) + { + xnOSWaitAndTerminateThread(&m_hListenThread, XN_SENSOR_CLIENT_TERMINATE_THREAD_TIMEOUT); + m_hListenThread = NULL; + } + + // now destroy it all + XnStreamReaderDevice::Destroy(); + + if (m_hReplyEvent != NULL) + { + xnOSCloseEvent(&m_hReplyEvent); + m_hReplyEvent = NULL; + } + + XN_DELETE(m_pOutgoingPacker); + + if (m_hLock != NULL) + { + xnOSCloseCriticalSection(&m_hLock); + m_hLock = NULL; + } + + return XN_STATUS_OK; +} + +XnStatus XnSensorClient::CreateStream(const XnChar* StreamType, const XnChar* StreamName /* = NULL */, const XnPropertySet* pInitialValues /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_PROPERTY_SET_CREATE_ON_STACK(props); + if (pInitialValues == NULL) + { + pInitialValues = &props; + } + + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Creating stream %s (of type %s)", StreamName, StreamType); + + nRetVal = m_pOutgoingPacker->WriteNewStream(StreamType, StreamName, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::DestroyStream(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Destroying stream %s", StreamName); + + // this might be called after connection was closed + if (m_bConnected) + { + nRetVal = m_pOutgoingPacker->WriteStreamRemoved(StreamName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + } + + XnStreamReaderDevice::DestroyStream(StreamName); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if we have a local copy + nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, pnValue); + if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) + { + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); + + // get from server (virtual property?) + XnSensorServerMessageGetPropertyRequest request; + strcpy(request.strModuleName, ModuleName); + strcpy(request.strPropertyName, PropertyName); + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, &request, sizeof(request)); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY); + XN_IS_STATUS_OK(nRetVal); + + *pnValue = *(XnUInt64*)m_LastReply.pData; + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if we have a local copy + nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, pdValue); + if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) + { + // get from server (virtual property?) + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); + XnSensorServerMessageGetPropertyRequest request; + strcpy(request.strModuleName, ModuleName); + strcpy(request.strPropertyName, PropertyName); + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, &request, sizeof(request)); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY); + XN_IS_STATUS_OK(nRetVal); + + *pdValue = *(XnDouble*)m_LastReply.pData; + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if we have a local copy + nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, strValue); + if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) + { + // get from server (virtual property?) + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); + XnSensorServerMessageGetPropertyRequest request; + strcpy(request.strModuleName, ModuleName); + strcpy(request.strPropertyName, PropertyName); + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, &request, sizeof(request)); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY); + XN_IS_STATUS_OK(nRetVal); + + strcpy(strValue, (const XnChar*)m_LastReply.pData); + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if we have a local copy + nRetVal = XnStreamReaderDevice::GetProperty(ModuleName, PropertyName, Value); + if (nRetVal == XN_STATUS_DEVICE_PROPERTY_DONT_EXIST) + { + // get from server (virtual property?) + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Getting property %s.%s from server...", ModuleName, PropertyName); + XnUInt32 nBufSize = sizeof(XnSensorServerMessageGetPropertyRequest) + Value.nDataSize; + XnUChar bufValue[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; + XnUChar* pBuf = bufValue; + + XnSensorServerMessageGetPropertyRequest* pRequest = (XnSensorServerMessageGetPropertyRequest*)pBuf; + XnUChar* pData = pBuf + sizeof(XnSensorServerMessageGetPropertyRequest); + + strcpy(pRequest->strModuleName, ModuleName); + strcpy(pRequest->strPropertyName, PropertyName); + pRequest->nSize = Value.nDataSize; + + // copy data + xnOSMemCopy(pData, Value.pData, Value.nDataSize); + + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, pBuf, nBufSize); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY); + XN_IS_STATUS_OK(nRetVal); + + xnOSMemCopy(Value.pData, m_LastReply.pData, m_LastReply.nDataSize); + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // there are some properties we don't change on the server (they affect only this client) + if (strcmp(ModuleName, XN_MODULE_NAME_DEVICE) == 0 && strcmp(PropertyName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) + { + nRetVal = XnStreamReaderDevice::SetProperty(ModuleName, PropertyName, nValue); + XN_IS_STATUS_OK(nRetVal); + } + else + { + // set it on the server + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %llu...", ModuleName, PropertyName, nValue); + + nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %f...", ModuleName, PropertyName, dValue); + + nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, dValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s to %s...", ModuleName, PropertyName, strValue); + + nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, strValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Setting %s.%s...", ModuleName, PropertyName); + + nRetVal = m_pOutgoingPacker->WriteProperty(ModuleName, PropertyName, Value); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::BatchConfig(const XnPropertySet* pChangeSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Batch configuring server..."); + + nRetVal = m_pOutgoingPacker->WritePropertySet(pChangeSet); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::ReadStream(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bConnected) + { + return (XN_STATUS_DEVICE_SERVER_DISCONNECTED); + } + + nRetVal = XnStreamReaderDevice::ReadStream(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::Read(XnStreamDataSet* pStreamOutputSet) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bConnected) + { + return (XN_STATUS_DEVICE_SERVER_DISCONNECTED); + } + + nRetVal = XnStreamReaderDevice::Read(pStreamOutputSet); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::SendBye() +{ + xnLogVerbose(XN_MASK_SENSOR_CLIENT, "Sending Bye"); + XnStatus nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_BYE, NULL, 0); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_BYE); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnSensorClient::HandlePackedObject(XnPackedDataType nObjectType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nDataSize = sizeof(m_LastReply); + + switch (nObjectType) + { + case XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND: + case XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY: + case XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY: + case XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY: + case XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY: + case XN_SENSOR_SERVER_MESSAGE_READ_STREAM: + case XN_SENSOR_SERVER_MESSAGE_BYE: + { + nRetVal = GetDataPacker()->ReadCustomData(nObjectType, &m_LastReply, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSSetEvent(m_hReplyEvent); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA: + { + XnSensorServerNewStreamData message; + XnUInt32 nDataSize = sizeof(message); + nRetVal = GetDataPacker()->ReadCustomData(nObjectType, &message, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + // find the stream + XnStreamDeviceStreamHolder* pHolder = NULL; + nRetVal = FindStream(message.strStreamName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + pHolder->GetStream()->NewDataAvailable(message.nTimestamp, message.nFrameID); + break; + } + default: + { + nRetVal = XnStreamReaderDevice::HandlePackedObject(nObjectType); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamReaderDevice::HandleNewStream(strType, strName, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + // open shared memory + XnStreamDeviceStreamHolder* pHolder = NULL; + nRetVal = FindStream(strName, &pHolder); + XN_IS_STATUS_OK(nRetVal); + + XnSensorClientStream* pStream = (XnSensorClientStream*)pHolder->GetStream(); + nRetVal = pStream->OpenSharedMemory(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // ignore some properties + if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_SENSOR_PROPERTY_INSTANCE_POINTER) == 0) + { + return (XN_STATUS_OK); + } + else + { + nRetVal = XnStreamReaderDevice::HandleGeneralProperty(strModule, strName, gbValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::WaitForReply(XnSensorServerCustomMessages ExpectedMessage) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // wait for event + nRetVal = xnOSWaitEvent(m_hReplyEvent, XN_SENSOR_REPLY_TIMEOUT); + if (nRetVal != XN_STATUS_OK) + { + XN_LOG_WARNING_RETURN(nRetVal, XN_MASK_SENSOR_SERVER, "Timeout when waiting for reply from sensor server!"); + } + + // reset it + nRetVal = xnOSResetEvent(m_hReplyEvent); + XN_IS_STATUS_OK(nRetVal); + + // check error code + if (m_LastReply.nRetVal != XN_STATUS_OK) + { + XN_LOG_WARNING_RETURN(m_LastReply.nRetVal, XN_MASK_SENSOR_SERVER, "Server returned an error: %s", xnGetStatusString(m_LastReply.nRetVal)); + } + + if (m_LastReply.Type != ExpectedMessage) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid reply type!"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnSensorServerMessageIniFile message; + strncpy(message.strFileName, csINIFilePath, XN_FILE_MAX_PATH); + strncpy(message.strSectionName, csSectionName, XN_DEVICE_MAX_STRING_LENGTH); + + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_INI_FILE, &message, sizeof(message)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::CreateIOStreamImpl(const XnChar *strConnectionString, XnIOStream *&pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSCreateSocket(XN_OS_TCP_SOCKET, XN_SENSOR_SERVER_IP_ADDRESS, XN_SENSOR_SERVER_PORT, &m_hSocket); + XN_IS_STATUS_OK(nRetVal); + + // connect to server + XnUInt64 nStart; + xnOSGetTimeStamp(&nStart); + + nRetVal = XN_STATUS_OS_NETWORK_TIMEOUT; + for (XnUInt32 nRetries = 0; (nRetries < XN_SENSOR_CLIENT_CONNECT_RETRIES) && (nRetVal != XN_STATUS_OK); nRetries++) + { + nRetVal = xnOSConnectSocket(m_hSocket, XN_SENSOR_CLIENT_WAIT_FOR_SERVER); + } + + if (nRetVal == XN_STATUS_OS_NETWORK_TIMEOUT) + { + xnLogError(XN_MASK_SENSOR_CLIENT, "Got timeout waiting for server"); + return nRetVal; + } + else if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_CLIENT, "Got an error trying to connect to server socket: %s", xnGetStatusString(nRetVal)); + return nRetVal; + } + + XnIONetworkStream *pNetworkStream = XN_NEW(XnIONetworkStream, m_hSocket); + if (pNetworkStream == NULL) + { + xnOSCloseSocket(m_hSocket); + return XN_STATUS_ALLOC_FAILED; + } + pNetworkStream->SetReadTimeout(XN_SENSOR_CLIENT_READ_TIMEOUT); + pStream = pNetworkStream; + + // create outgoing data packer (incoming is created by base class) + m_pOutgoingPacker = XN_NEW(XnDataPacker, pNetworkStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE); + if (m_pOutgoingPacker == NULL) + { + XN_DELETE(pNetworkStream); + xnOSCloseSocket(m_hSocket); + return XN_STATUS_ALLOC_FAILED; + } + + nRetVal = m_pOutgoingPacker->Init(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pNetworkStream); + XN_DELETE(m_pOutgoingPacker); + xnOSCloseSocket(m_hSocket); + return nRetVal; + } + + // send server a request to open the sensor + nRetVal = m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, strConnectionString, strlen(strConnectionString) + 1); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pNetworkStream); + XN_DELETE(m_pOutgoingPacker); + xnOSCloseSocket(m_hSocket); + return nRetVal; + } + + return (XN_STATUS_OK); +} + +void XnSensorClient::DestroyIOStreamImpl(XnIOStream* pStream) +{ + XN_DELETE(pStream); + if (m_hSocket != NULL) + { + xnOSCloseSocket(m_hSocket); + m_hSocket = NULL; + } +} + +XnStatus XnSensorClient::CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDeviceBase::CreateDeviceModule(ppModuleHolder); + XN_IS_STATUS_OK(nRetVal); + + // add sensor properties + XnDeviceModule* pModule = (*ppModuleHolder)->GetModule(); + XnProperty* pProps[] = { &m_InstancePointer, &m_ErrorState }; + + nRetVal = pModule->AddProperties(pProps, sizeof(pProps)/sizeof(XnProperty*)); + if (nRetVal != XN_STATUS_OK) + { + DestroyModule(*ppModuleHolder); + *ppModuleHolder = NULL; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClient::CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnSensorClientStream* pStream; + if (strcmp(StreamType, XN_STREAM_TYPE_AUDIO) == 0) + { + XN_VALIDATE_NEW(pStream, XnSensorClientAudioStream, this, StreamType, StreamName); + } + else + { + XN_VALIDATE_NEW(pStream, XnSensorClientFrameStream, this, StreamType, StreamName); + } + + XnStreamReaderStreamHolder* pHolder = XN_NEW(XnStreamReaderStreamHolder, pStream); + if (pHolder == NULL) + { + XN_DELETE(pStream); + return XN_STATUS_ALLOC_FAILED; + } + + *ppStreamHolder = pHolder; + + return (XN_STATUS_OK); +} + +void XnSensorClient::DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder) +{ + XN_DELETE(pStreamHolder->GetModule()); + XN_DELETE(pStreamHolder); +} + +XnStatus XnSensorClient::Listen() +{ + XnStatus nRetVal = XN_STATUS_OK; + + while (m_bShouldRun) + { + nRetVal = ReadNextEventFromStream(); + if (nRetVal == XN_STATUS_OS_NETWORK_TIMEOUT) + { + continue; + } + else if ((nRetVal == XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) && !m_bShouldRun) + { + xnLogInfo(XN_MASK_SENSOR_CLIENT, "Client connection was closed gracefully"); + } + else if (nRetVal != XN_STATUS_OK) + { + XnIONetworkStream* pStream = (XnIONetworkStream*)GetIOStream(); + if (!pStream->IsConnected()) + { + m_bConnected = FALSE; + xnLogError(XN_MASK_SENSOR_CLIENT, "Server has disconnected!"); + break; + } + else + { + xnLogWarning(XN_MASK_SENSOR_CLIENT, "Sensor client failed to handle event: %s", xnGetStatusString(nRetVal)); + } + } + } + + return (XN_STATUS_OK); +} + +XN_THREAD_PROC XnSensorClient::ListenThread(XN_THREAD_PARAM pThreadParam) +{ + XnSensorClient* pThis = (XnSensorClient*)pThreadParam; + XnStatus nRetVal = pThis->Listen(); + XN_THREAD_PROC_RETURN(nRetVal); +} + +XnStatus XnSensorClient::StartServerProcess() +{ + XnStatus nRetVal = XN_STATUS_OK; + + const XnChar* strServerDir; + +#if (XN_PLATFORM == XN_PLATFORM_WIN32) + strServerDir = ms_strDir; +#elif (XN_PLATFORM == XN_PLATFORM_LINUX_X86 || XN_PLATFORM == XN_PLATFORM_LINUX_ARM || XN_PLATFORM == XN_PLATFORM_MACOSX) + strServerDir = "/usr/bin"; +#endif + + // we'll start it in it's directory + XnChar strCurrDir[XN_FILE_MAX_PATH]; + nRetVal = xnOSGetCurrentDir(strCurrDir, XN_FILE_MAX_PATH); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSSetCurrentDir(strServerDir); + XN_IS_STATUS_OK(nRetVal); + + XnChar strProcessName[XN_FILE_MAX_PATH]; + sprintf(strProcessName, "%s%sXnSensorServer", strServerDir, XN_FILE_DIR_SEP); + +#if (XN_PLATFORM == XN_PLATFORM_WIN32) + XN_VALIDATE_STR_APPEND(strProcessName, ".exe", XN_FILE_MAX_PATH, nRetVal); +#endif + + const XnChar* strArguments[] = { m_strConfigDir }; + + XN_PROCESS_ID procID; + nRetVal = xnOSCreateProcess(strProcessName, 1, strArguments, &procID); + + // in any case, return to working dir + xnOSSetCurrentDir(strCurrDir); + + // now check for errors + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorClient.h b/Source/XnDeviceSensorV2/XnSensorClient.h index 09b1fb6..f4d7462 100644 --- a/Source/XnDeviceSensorV2/XnSensorClient.h +++ b/Source/XnDeviceSensorV2/XnSensorClient.h @@ -1,114 +1,114 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_CLIENT_H__ -#define __XN_SENSOR_CLIENT_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnSensorClientServer.h" - -//--------------------------------------------------------------------------- -// XnSensorClient class -//--------------------------------------------------------------------------- -class XnSensorClient : public XnStreamReaderDevice -{ -public: - XnSensorClient(); - virtual ~XnSensorClient(); - - static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); - static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); - - XnStatus Init(const XnDeviceConfig* pDeviceConfig); - XnStatus Destroy(); - XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); - XnStatus DestroyStream(const XnChar* StreamName); - XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue); - XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue); - XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* strValue); - XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue); - XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); - XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); - XnStatus BatchConfig(const XnPropertySet* pChangeSet); - XnStatus ReadStream(XnStreamData* pStreamOutput); - XnStatus Read(XnStreamDataSet* pStreamOutputSet); - - void SetConfigDir(const XnChar* strConfigDir); - - static XnStatus TakeServerLocation(); - -protected: - XnStatus SendBye(); - virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); - virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); - virtual void DestroyIOStreamImpl(XnIOStream* pStream); - virtual XnStatus ReadInitialState(XnPropertySet* pSet); - - XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); - XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); - void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); - - virtual XnStatus HandlePackedObject(XnPackedDataType nObjectType); - virtual XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); - virtual XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); - - XnStatus WaitForReply(XnSensorServerCustomMessages ExpectedMessage); - -private: - friend class XnSensorClientStream; - friend class XnSensorClientFrameStream; - - XnStatus Listen(); - XnStatus StartServerProcess(); - - static XN_THREAD_PROC ListenThread(XN_THREAD_PARAM pThreadParam); - - XN_SOCKET_HANDLE m_hSocket; - XN_EVENT_HANDLE m_hReplyEvent; - XN_THREAD_HANDLE m_hListenThread; - volatile XnBool m_bShouldRun; - XnDataPacker* m_pOutgoingPacker; - XnSensorClientServerReply m_LastReply; - XnBool m_bConnected; - - XnSensorClient* m_pThis; - XnActualGeneralProperty m_InstancePointer; - XnActualIntProperty m_ErrorState; - - XN_CRITICAL_SECTION_HANDLE m_hLock; - XnChar m_strConfigDir[XN_FILE_MAX_PATH]; - - static XnChar ms_strDir[]; -}; - -#endif //__XN_SENSOR_CLIENT_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_CLIENT_H__ +#define __XN_SENSOR_CLIENT_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnSensorClientServer.h" + +//--------------------------------------------------------------------------- +// XnSensorClient class +//--------------------------------------------------------------------------- +class XnSensorClient : public XnStreamReaderDevice +{ +public: + XnSensorClient(); + virtual ~XnSensorClient(); + + static XnStatus GetDefinition(XnDeviceDefinition* pDeviceDefinition); + static XnStatus Enumerate(XnConnectionString* aConnectionStrings, XnUInt32* pnCount); + + XnStatus Init(const XnDeviceConfig* pDeviceConfig); + XnStatus Destroy(); + XnStatus CreateStream(const XnChar* StreamType, const XnChar* StreamName = NULL, const XnPropertySet* pInitialValues = NULL); + XnStatus DestroyStream(const XnChar* StreamName); + XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64* pnValue); + XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble* pdValue); + XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnChar* strValue); + XnStatus GetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnUInt64 nValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, XnDouble dValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnChar* strValue); + XnStatus SetProperty(const XnChar* ModuleName, const XnChar* PropertyName, const XnGeneralBuffer& Value); + XnStatus LoadConfigFromFile(const XnChar* csINIFilePath, const XnChar* csSectionName); + XnStatus BatchConfig(const XnPropertySet* pChangeSet); + XnStatus ReadStream(XnStreamData* pStreamOutput); + XnStatus Read(XnStreamDataSet* pStreamOutputSet); + + void SetConfigDir(const XnChar* strConfigDir); + + static XnStatus TakeServerLocation(); + +protected: + XnStatus SendBye(); + virtual XnStatus InitImpl(const XnDeviceConfig* pDeviceConfig); + virtual XnStatus CreateIOStreamImpl(const XnChar* strConnectionString, XnIOStream*& pStream); + virtual void DestroyIOStreamImpl(XnIOStream* pStream); + virtual XnStatus ReadInitialState(XnPropertySet* pSet); + + XnStatus CreateDeviceModule(XnDeviceModuleHolder** ppModuleHolder); + XnStatus CreateStreamModule(const XnChar* StreamType, const XnChar* StreamName, XnDeviceModuleHolder** ppStreamHolder); + void DestroyStreamModule(XnDeviceModuleHolder* pStreamHolder); + + virtual XnStatus HandlePackedObject(XnPackedDataType nObjectType); + virtual XnStatus HandleNewStream(const XnChar* strType, const XnChar* strName, const XnActualPropertiesHash* pInitialValues); + virtual XnStatus HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue); + + XnStatus WaitForReply(XnSensorServerCustomMessages ExpectedMessage); + +private: + friend class XnSensorClientStream; + friend class XnSensorClientFrameStream; + + XnStatus Listen(); + XnStatus StartServerProcess(); + + static XN_THREAD_PROC ListenThread(XN_THREAD_PARAM pThreadParam); + + XN_SOCKET_HANDLE m_hSocket; + XN_EVENT_HANDLE m_hReplyEvent; + XN_THREAD_HANDLE m_hListenThread; + volatile XnBool m_bShouldRun; + XnDataPacker* m_pOutgoingPacker; + XnSensorClientServerReply m_LastReply; + XnBool m_bConnected; + + XnSensorClient* m_pThis; + XnActualGeneralProperty m_InstancePointer; + XnActualIntProperty m_ErrorState; + + XN_CRITICAL_SECTION_HANDLE m_hLock; + XnChar m_strConfigDir[XN_FILE_MAX_PATH]; + + static XnChar ms_strDir[]; +}; + +#endif //__XN_SENSOR_CLIENT_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorClientServer.h b/Source/XnDeviceSensorV2/XnSensorClientServer.h index cfb06c6..f14e797 100644 --- a/Source/XnDeviceSensorV2/XnSensorClientServer.h +++ b/Source/XnDeviceSensorV2/XnSensorClientServer.h @@ -1,117 +1,118 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_CLIENT_SERVER_H__ -#define __XN_SENSOR_CLIENT_SERVER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Definitions -//--------------------------------------------------------------------------- -#define XN_SENSOR_SERVER_IP_ADDRESS XN_OS_NETWORK_LOCAL_HOST -#define XN_SENSOR_SERVER_PORT 18180 -#define XN_SENSOR_SERVER_MAX_MESSAGE_SIZE (4 * 1024 * 1024) -#define XN_SENSOR_SERVER_CONFIG_PACKER_SIZE (100 * 1024) -#define XN_SENSOR_SERVER_MAX_REPLY_SIZE (40 * 1024) -#define XN_SENSOR_REPLY_TIMEOUT 30000 -#define XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT 15000 -#define XN_MASK_SENSOR_SERVER "SensorServer" -#define XN_SENSOR_SERVER_RUNNING_EVENT_NAME "XnSensorServerRunningEvent" -#define XN_SENSOR_SERVER_RUNNING_MUTEX_NAME "XnSensorServerRunningMutex" - -//--------------------------------------------------------------------------- -// Enums -//--------------------------------------------------------------------------- -typedef enum XnSensorServerCustomMessages -{ - XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND = XN_PACKED_CUSTOM_MESSAGE + 1, - XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, - XN_SENSOR_SERVER_MESSAGE_INI_FILE, - XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, - XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, - XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, - XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, - XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA, - XN_SENSOR_SERVER_MESSAGE_READ_STREAM, - XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM, - XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM, - XN_SENSOR_SERVER_MESSAGE_BYE, -} XnSensorServerCustomMessages; - -//--------------------------------------------------------------------------- -// Structs -//--------------------------------------------------------------------------- -#pragma pack (push, 1) - -typedef struct XnSensorClientServerReply -{ - XnStatus nRetVal; - XnSensorServerCustomMessages Type; - XnUInt32 nDataSize; - XnUChar pData[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; -} XnSensorClientServerReply; - -typedef struct XnSensorServerMessageIniFile -{ - XnChar strFileName[XN_FILE_MAX_PATH]; - XnChar strSectionName[XN_DEVICE_MAX_STRING_LENGTH]; -} XnSensorServerMessageIniFile; - -typedef struct XnSensorServerMessageGetPropertyRequest -{ - XnChar strModuleName[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strPropertyName[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nSize; -} XnSensorServerMessageGetPropertyRequest; - -typedef struct XnSensorServerGetGeneralPropReply -{ - XnUInt32 nSize; - XnUChar pData[XN_SENSOR_SERVER_MAX_REPLY_SIZE - 50]; -} XnSensorServerGetGeneralPropReply; - -typedef struct XnSensorServerNewStreamData -{ - XnUInt64 nTimestamp; - XnUInt32 nFrameID; - XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; -} XnSensorServerNewStreamData; - -typedef struct XnSensorServerReadReply -{ - XnUInt64 nTimestamp; - XnUInt32 nOffset; - XnUInt32 nDataSize; - XnUInt32 nFrameID; -} XnSensorServerReadReply; - -#pragma pack (pop) - -#endif //__XN_SENSOR_CLIENT_SERVER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_CLIENT_SERVER_H__ +#define __XN_SENSOR_CLIENT_SERVER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Definitions +//--------------------------------------------------------------------------- +#define XN_SENSOR_SERVER_IP_ADDRESS XN_OS_NETWORK_LOCAL_HOST +#define XN_SENSOR_SERVER_PORT 18180 +#define XN_SENSOR_SERVER_MAX_MESSAGE_SIZE (4 * 1024 * 1024) +#define XN_SENSOR_SERVER_CONFIG_PACKER_SIZE (100 * 1024) +#define XN_SENSOR_SERVER_MAX_REPLY_SIZE (40 * 1024) +#define XN_SENSOR_REPLY_TIMEOUT 30000 +#define XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT 15000 +#define XN_MASK_SENSOR_SERVER "SensorServer" +#define XN_SENSOR_SERVER_RUNNING_EVENT_NAME "XnSensorServerRunningEvent" +#define XN_SENSOR_SERVER_RUNNING_MUTEX_NAME "XnSensorServerRunningMutex" +#define XN_SENSOR_SERVER_CONFIG_FILE_SECTION "Server" + +//--------------------------------------------------------------------------- +// Enums +//--------------------------------------------------------------------------- +typedef enum XnSensorServerCustomMessages +{ + XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND = XN_PACKED_CUSTOM_MESSAGE + 1, + XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, + XN_SENSOR_SERVER_MESSAGE_INI_FILE, + XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, + XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, + XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, + XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, + XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA, + XN_SENSOR_SERVER_MESSAGE_READ_STREAM, + XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM, + XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM, + XN_SENSOR_SERVER_MESSAGE_BYE, +} XnSensorServerCustomMessages; + +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- +#pragma pack (push, 1) + +typedef struct XnSensorClientServerReply +{ + XnStatus nRetVal; + XnSensorServerCustomMessages Type; + XnUInt32 nDataSize; + XnUChar pData[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; +} XnSensorClientServerReply; + +typedef struct XnSensorServerMessageIniFile +{ + XnChar strFileName[XN_FILE_MAX_PATH]; + XnChar strSectionName[XN_DEVICE_MAX_STRING_LENGTH]; +} XnSensorServerMessageIniFile; + +typedef struct XnSensorServerMessageGetPropertyRequest +{ + XnChar strModuleName[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strPropertyName[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nSize; +} XnSensorServerMessageGetPropertyRequest; + +typedef struct XnSensorServerGetGeneralPropReply +{ + XnUInt32 nSize; + XnUChar pData[XN_SENSOR_SERVER_MAX_REPLY_SIZE - 50]; +} XnSensorServerGetGeneralPropReply; + +typedef struct XnSensorServerNewStreamData +{ + XnUInt64 nTimestamp; + XnUInt32 nFrameID; + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; +} XnSensorServerNewStreamData; + +typedef struct XnSensorServerReadReply +{ + XnUInt64 nTimestamp; + XnUInt32 nOffset; + XnUInt32 nDataSize; + XnUInt32 nFrameID; +} XnSensorServerReadReply; + +#pragma pack (pop) + +#endif //__XN_SENSOR_CLIENT_SERVER_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorClientStream.cpp b/Source/XnDeviceSensorV2/XnSensorClientStream.cpp index c37bfe6..0882996 100644 --- a/Source/XnDeviceSensorV2/XnSensorClientStream.cpp +++ b/Source/XnDeviceSensorV2/XnSensorClientStream.cpp @@ -1,244 +1,288 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorClientStream.h" -#include "XnSensorClient.h" -#include - -//--------------------------------------------------------------------------- -// Client Stream -//--------------------------------------------------------------------------- -XnSensorClientStream::XnSensorClientStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : - XnStreamReaderStream(strType, strName), - m_pClient(pClient), - m_hSharedMemory(NULL), - m_pSharedMemory(NULL) -{} - -XnSensorClientStream::~XnSensorClientStream() -{ - XnSensorClientStream::Free(); -} - -XnStatus XnSensorClientStream::OpenSharedMemory() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_hSharedMemory != NULL) - { - xnOSCloseSharedMemory(m_hSharedMemory); - m_hSharedMemory = NULL; - m_pSharedMemory = NULL; - } - - XnChar strSharedMemoryName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = GetProperty(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, strSharedMemoryName); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSOpenSharedMemory(strSharedMemoryName, XN_OS_FILE_READ, &m_hSharedMemory); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, (void**)&m_pSharedMemory); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClientStream::Open() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM, GetName(), strlen(GetName()) + 1); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnStreamReaderStream::Open(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClientStream::Close() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read data from server - nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM, GetName(), strlen(GetName()) + 1); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnStreamReaderStream::Close(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClientStream::Free() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_hSharedMemory != NULL) - { - xnOSCloseSharedMemory(m_hSharedMemory); - m_hSharedMemory = NULL; - m_pSharedMemory = NULL; - } - - return (XN_STATUS_OK); -} - -//--------------------------------------------------------------------------- -// Client Frame Stream -//--------------------------------------------------------------------------- -XnSensorClientFrameStream::XnSensorClientFrameStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : - XnSensorClientStream(pClient, strType, strName), - m_nFrameID(0) -{} - -XnSensorClientFrameStream::~XnSensorClientFrameStream() -{ -} - -XnStatus XnSensorClientFrameStream::ReadImpl(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read data from server - nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_READ_STREAM, pStreamOutput->StreamName, strlen(pStreamOutput->StreamName) + 1); - XN_IS_STATUS_OK(nRetVal); - - // wait for reply - nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_READ_STREAM); - XN_IS_STATUS_OK(nRetVal); - - ++m_nFrameID; - - XnSensorServerReadReply* pReply = (XnSensorServerReadReply*)m_pClient->m_LastReply.pData; - pStreamOutput->nFrameID = m_nFrameID; - pStreamOutput->nTimestamp = pReply->nTimestamp; - pStreamOutput->pData = (m_pSharedMemory + pReply->nOffset); - pStreamOutput->nDataSize = pReply->nDataSize; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClientFrameStream::CreateStreamData(XnStreamData** ppStreamData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamData* pStreamData; - - // we create a StreamData object with no buffer allocated. The buffer will just be - // a pointer to the triple buffer - nRetVal = XnStreamDataCreateNoBuffer(&pStreamData, GetName()); - XN_IS_STATUS_OK(nRetVal); - - pStreamData->pData = m_pSharedMemory; - - *ppStreamData = pStreamData; - - return (XN_STATUS_OK); -} - -//--------------------------------------------------------------------------- -// Client Audio Stream -//--------------------------------------------------------------------------- -XnSensorClientAudioStream::XnSensorClientAudioStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : - XnSensorClientStream(pClient, strType, strName), - m_pHeader(NULL), - m_pBuffer(NULL), - m_nLastReadIndex(0) -{} - -XnSensorClientAudioStream::~XnSensorClientAudioStream() -{} - -XnStatus XnSensorClientAudioStream::OpenSharedMemory() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorClientStream::OpenSharedMemory(); - XN_IS_STATUS_OK(nRetVal); - - m_pHeader = (XnAudioSharedBuffer*)m_pSharedMemory; - m_pBuffer = m_pSharedMemory + m_pHeader->nBufferOffset; - m_pTimestamps = (XnUInt64*)(m_pSharedMemory + m_pHeader->nTimestampsListOffset); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorClientAudioStream::ReadImpl(XnStreamData* pStreamOutput) -{ - XnStatus nRetVal = XN_STATUS_OK; - - pStreamOutput->nDataSize = 0; - - // take last write index - XnUInt32 nWriteIndex = m_pHeader->nWritePacketIndex; - - // take timestamp - pStreamOutput->nTimestamp = m_pTimestamps[m_nLastReadIndex]; - - // check how many buffers we have - XnInt32 nAvailbalePackets = nWriteIndex - m_nLastReadIndex; - if (nAvailbalePackets < 0) - nAvailbalePackets += m_pHeader->nPacketCount; - - // make sure we have enough space - while (GetRequiredDataSize() < (XnUInt32)nAvailbalePackets * m_pHeader->nPacketSize) - { - m_nLastReadIndex = (m_nLastReadIndex + 1) % m_pHeader->nPacketCount; - nAvailbalePackets--; - } - - // now copy data from last read position to this one - XnUChar* pAudioBuf = (XnUChar*)pStreamOutput->pData; - - // copy - while (m_nLastReadIndex != nWriteIndex) - { - XN_ASSERT(pStreamOutput->nDataSize < GetRequiredDataSize()); - - XnUChar* pPacketData = m_pBuffer + (m_nLastReadIndex * m_pHeader->nPacketSize); - xnOSMemCopy(pAudioBuf, pPacketData, m_pHeader->nPacketSize); - pAudioBuf += m_pHeader->nPacketSize; - pStreamOutput->nDataSize += m_pHeader->nPacketSize; - - m_nLastReadIndex = (m_nLastReadIndex + 1) % m_pHeader->nPacketCount; - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorClientStream.h" +#include "XnSensorClient.h" +#include + +//--------------------------------------------------------------------------- +// Client Stream +//--------------------------------------------------------------------------- +XnSensorClientStream::XnSensorClientStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : + XnStreamReaderStream(strType, strName), + m_pClient(pClient), + m_hSharedMemory(NULL), + m_pSharedMemory(NULL) +{} + +XnSensorClientStream::~XnSensorClientStream() +{ + XnSensorClientStream::Free(); +} + +XnStatus XnSensorClientStream::OpenSharedMemory() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_hSharedMemory != NULL) + { + xnOSCloseSharedMemory(m_hSharedMemory); + m_hSharedMemory = NULL; + m_pSharedMemory = NULL; + } + + XnChar strSharedMemoryName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = GetProperty(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, strSharedMemoryName); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSOpenSharedMemory(strSharedMemoryName, XN_OS_FILE_READ, &m_hSharedMemory); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, (void**)&m_pSharedMemory); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientStream::Open() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM, GetName(), strlen(GetName()) + 1); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnStreamReaderStream::Open(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientStream::Close() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read data from server + nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM, GetName(), strlen(GetName()) + 1); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnStreamReaderStream::Close(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientStream::Free() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_hSharedMemory != NULL) + { + xnOSCloseSharedMemory(m_hSharedMemory); + m_hSharedMemory = NULL; + m_pSharedMemory = NULL; + } + + return (XN_STATUS_OK); +} + +//--------------------------------------------------------------------------- +// Client Frame Stream +//--------------------------------------------------------------------------- +XnSensorClientFrameStream::XnSensorClientFrameStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : + XnSensorClientStream(pClient, strType, strName), + m_nFrameID(0) +{} + +XnSensorClientFrameStream::~XnSensorClientFrameStream() +{ +} + +XnStatus XnSensorClientFrameStream::ReadImpl(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read data from server + nRetVal = m_pClient->m_pOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_READ_STREAM, pStreamOutput->StreamName, strlen(pStreamOutput->StreamName) + 1); + XN_IS_STATUS_OK(nRetVal); + + // wait for reply + nRetVal = m_pClient->WaitForReply(XN_SENSOR_SERVER_MESSAGE_READ_STREAM); + XN_IS_STATUS_OK(nRetVal); + + ++m_nFrameID; + + XnSensorServerReadReply* pReply = (XnSensorServerReadReply*)m_pClient->m_LastReply.pData; + pStreamOutput->nFrameID = m_nFrameID; + pStreamOutput->nTimestamp = pReply->nTimestamp; + pStreamOutput->pData = (m_pSharedMemory + pReply->nOffset); + pStreamOutput->nDataSize = pReply->nDataSize; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientFrameStream::CreateStreamData(XnStreamData** ppStreamData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamData* pStreamData; + + // we create a StreamData object with no buffer allocated. The buffer will just be + // a pointer to the triple buffer + nRetVal = XnStreamDataCreateNoBuffer(&pStreamData, GetName()); + XN_IS_STATUS_OK(nRetVal); + + pStreamData->pData = m_pSharedMemory; + + *ppStreamData = pStreamData; + + return (XN_STATUS_OK); +} + +//--------------------------------------------------------------------------- +// Client Audio Stream +//--------------------------------------------------------------------------- +XnSensorClientAudioStream::XnSensorClientAudioStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName) : + XnSensorClientStream(pClient, strType, strName), + m_pHeader(NULL), + m_pBuffer(NULL), + m_nLastReadIndex(0), + m_hLock(NULL) +{} + +XnSensorClientAudioStream::~XnSensorClientAudioStream() +{} + +XnStatus XnSensorClientAudioStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorClientStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientAudioStream::Free() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_hLock != NULL) + { + xnOSCloseCriticalSection(&m_hLock); + m_hLock = NULL; + } + + nRetVal = XnSensorClientStream::Free(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorClientAudioStream::OpenSharedMemory() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorClientStream::OpenSharedMemory(); + XN_IS_STATUS_OK(nRetVal); + + m_pHeader = (XnAudioSharedBuffer*)m_pSharedMemory; + m_pBuffer = m_pSharedMemory + m_pHeader->nBufferOffset; + m_pTimestamps = (XnUInt64*)(m_pSharedMemory + m_pHeader->nTimestampsListOffset); + + return (XN_STATUS_OK); +} + +void XnSensorClientAudioStream::NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID) +{ + // if a read is in progress, wait for it to complete + XnAutoCSLocker locker(m_hLock); + + // check if we still have new data + if (m_pHeader->nWritePacketIndex != m_nLastReadIndex) + { + XnSensorClientStream::NewDataAvailable(m_pTimestamps[m_nLastReadIndex], 0); + } +} + +XnStatus XnSensorClientAudioStream::ReadImpl(XnStreamData* pStreamOutput) +{ + XnStatus nRetVal = XN_STATUS_OK; + + pStreamOutput->nDataSize = 0; + + // take last write index (note: this is taken from shared memory) + XnAutoCSLocker locker(m_hLock); + + XnUInt32 nWriteIndex = m_pHeader->nWritePacketIndex; + + // check how many buffers we have + XnInt32 nAvailbalePackets = nWriteIndex - m_nLastReadIndex; + if (nAvailbalePackets < 0) + nAvailbalePackets += m_pHeader->nPacketCount; + + // make sure we have enough space + while (GetRequiredDataSize() < (XnUInt32)nAvailbalePackets * m_pHeader->nPacketSize) + { + m_nLastReadIndex = (m_nLastReadIndex + 1) % m_pHeader->nPacketCount; + nAvailbalePackets--; + } + + // take timestamp + pStreamOutput->nTimestamp = m_pTimestamps[m_nLastReadIndex]; + + // now copy data from last read position to this one + XnUChar* pAudioBuf = (XnUChar*)pStreamOutput->pData; + + // copy + while (m_nLastReadIndex != nWriteIndex) + { + XN_ASSERT(pStreamOutput->nDataSize < GetRequiredDataSize()); + + XnUChar* pPacketData = m_pBuffer + (m_nLastReadIndex * m_pHeader->nPacketSize); + xnOSMemCopy(pAudioBuf, pPacketData, m_pHeader->nPacketSize); + pAudioBuf += m_pHeader->nPacketSize; + pStreamOutput->nDataSize += m_pHeader->nPacketSize; + + m_nLastReadIndex = (m_nLastReadIndex + 1) % m_pHeader->nPacketCount; + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/XnSensorClientStream.h b/Source/XnDeviceSensorV2/XnSensorClientStream.h index 3e12afc..0744433 100644 --- a/Source/XnDeviceSensorV2/XnSensorClientStream.h +++ b/Source/XnDeviceSensorV2/XnSensorClientStream.h @@ -1,98 +1,104 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_CLIENT_STREAM_H__ -#define __XN_SENSOR_CLIENT_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnDeviceSensor.h" - -class XnSensorClient; - -//--------------------------------------------------------------------------- -// Client Stream -//--------------------------------------------------------------------------- -class XnSensorClientStream : public XnStreamReaderStream -{ -public: - XnSensorClientStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); - ~XnSensorClientStream(); - - XnStatus Free(); - virtual XnStatus OpenSharedMemory(); - virtual XnStatus Open(); - virtual XnStatus Close(); - -protected: - XnSensorClient* m_pClient; - XN_SHARED_MEMORY_HANDLE m_hSharedMemory; - XnUChar* m_pSharedMemory; -}; - -//--------------------------------------------------------------------------- -// Client Frame Stream -//--------------------------------------------------------------------------- -class XnSensorClientFrameStream : public XnSensorClientStream -{ -public: - XnSensorClientFrameStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); - ~XnSensorClientFrameStream(); - - XnStatus CreateStreamData(XnStreamData** ppStreamData); - -protected: - XnStatus ReadImpl(XnStreamData* pStreamOutput); - -private: - XnUInt32 m_nFrameID; -}; - -//--------------------------------------------------------------------------- -// Client Audio Stream -//--------------------------------------------------------------------------- -class XnSensorClientAudioStream : public XnSensorClientStream -{ -public: - XnSensorClientAudioStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); - ~XnSensorClientAudioStream(); - - XnStatus OpenSharedMemory(); - -protected: - XnStatus ReadImpl(XnStreamData* pStreamOutput); - -private: - XnAudioSharedBuffer* m_pHeader; - XnUChar* m_pBuffer; - XnUInt32 m_nLastReadIndex; - XnUInt64* m_pTimestamps; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_CLIENT_STREAM_H__ +#define __XN_SENSOR_CLIENT_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnDeviceSensor.h" + +class XnSensorClient; + +//--------------------------------------------------------------------------- +// Client Stream +//--------------------------------------------------------------------------- +class XnSensorClientStream : public XnStreamReaderStream +{ +public: + XnSensorClientStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); + ~XnSensorClientStream(); + + XnStatus Free(); + virtual XnStatus OpenSharedMemory(); + virtual XnStatus Open(); + virtual XnStatus Close(); + +protected: + XnSensorClient* m_pClient; + XN_SHARED_MEMORY_HANDLE m_hSharedMemory; + XnUChar* m_pSharedMemory; +}; + +//--------------------------------------------------------------------------- +// Client Frame Stream +//--------------------------------------------------------------------------- +class XnSensorClientFrameStream : public XnSensorClientStream +{ +public: + XnSensorClientFrameStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); + ~XnSensorClientFrameStream(); + + XnStatus CreateStreamData(XnStreamData** ppStreamData); + +protected: + XnStatus ReadImpl(XnStreamData* pStreamOutput); + +private: + XnUInt32 m_nFrameID; +}; + +//--------------------------------------------------------------------------- +// Client Audio Stream +//--------------------------------------------------------------------------- +class XnSensorClientAudioStream : public XnSensorClientStream +{ +public: + XnSensorClientAudioStream(XnSensorClient* pClient, const XnChar* strType, const XnChar* strName); + ~XnSensorClientAudioStream(); + + XnStatus Init(); + XnStatus Free(); + + XnStatus OpenSharedMemory(); + + virtual void NewDataAvailable(XnUInt64 nTimestamp, XnUInt32 nFrameID); + +protected: + XnStatus ReadImpl(XnStreamData* pStreamOutput); + +private: + XnAudioSharedBuffer* m_pHeader; + XnUChar* m_pBuffer; + XnUInt32 m_nLastReadIndex; + XnUInt64* m_pTimestamps; + XN_CRITICAL_SECTION_HANDLE m_hLock; +}; + #endif // __XN_SENSOR_CLIENT_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorDepthGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorDepthGenerator.cpp index 6c742d8..3d66c35 100644 --- a/Source/XnDeviceSensorV2/XnSensorDepthGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorDepthGenerator.cpp @@ -1,344 +1,344 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorDepthGenerator.h" -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// XnSensorDepthGenerator class -//--------------------------------------------------------------------------- - -XnSensorDepthGenerator::XnSensorDepthGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorMapGenerator(context, sensor, pSensor, strStreamName) -{ -} - -XnSensorDepthGenerator::~XnSensorDepthGenerator() -{ - if (m_hRWPropCallback) - { - UnregisterFromProps(m_hRWPropCallback); - } -} - -XnStatus XnSensorDepthGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorMapGenerator::Init(); - XN_IS_STATUS_OK(nRetVal); - - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, - XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, - NULL - }; - - m_hRWPropCallback; - nRetVal = RegisterToProps(RealWorldTranslationPropChanged, this, m_hRWPropCallback, aProps); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = UpdateRealWorldTranslationData(); - if (nRetVal != XN_STATUS_OK) - { - UnregisterFromProps(m_hRWPropCallback); - m_hRWPropCallback = NULL; - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnBool XnSensorDepthGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return (strcmp(strCapabilityName, XN_CAPABILITY_USER_POSITION) == 0 || - strcmp(strCapabilityName, XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) == 0 || - strcmp(strCapabilityName, XN_CAPABILITY_FRAME_SYNC) == 0 || - XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName)); -} - -XnDepthPixel* XnSensorDepthGenerator::GetDepthMap() -{ - return (XnDepthPixel*)m_pStreamData->pData; -} - -XnDepthPixel XnSensorDepthGenerator::GetDeviceMaxDepth() -{ - XnUInt64 nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &nValue); - return (XnDepthPixel)nValue; -} - -void XnSensorDepthGenerator::GetFieldOfView(XnFieldOfView& FOV) -{ - FOV = m_FOV; -} - -XnStatus XnSensorDepthGenerator::RegisterToFieldOfViewChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - return m_fovChangedEvent.Register(handler, pCookie, &hCallback); -} - -void XnSensorDepthGenerator::UnregisterFromFieldOfViewChange(XnCallbackHandle hCallback) -{ - m_fovChangedEvent.Unregister(hCallback); -} - -XnStatus XnSensorDepthGenerator::UpdateRealWorldTranslationData() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nZPD; - nRetVal = GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nZPD); - XN_IS_STATUS_OK(nRetVal); - - XnDouble fZPPS; - nRetVal = GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, fZPPS); - XN_IS_STATUS_OK(nRetVal); - - m_FOV.fHFOV = 2*atan(fZPPS*XN_SXGA_X_RES/2/nZPD); - m_FOV.fVFOV = 2*atan(fZPPS*XN_VGA_Y_RES*2/2/nZPD); - - nRetVal = m_fovChangedEvent.Raise(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnSensorDepthGenerator::RealWorldTranslationPropChanged(void* pCookie) -{ - XnSensorDepthGenerator* pThis = (XnSensorDepthGenerator*)pCookie; - pThis->UpdateRealWorldTranslationData(); -} - -XnUInt32 XnSensorDepthGenerator::GetSupportedUserPositionsCount() -{ - return 4; -} - -XnStatus XnSensorDepthGenerator::SetUserPosition(XnUInt32 nIndex, const XnBoundingBox3D& Position) -{ - // set (we only support Z boxing for now) - XnDepthAGCBin bin; - bin.nBin = nIndex; - bin.nMin = Position.LeftBottomNear.Z; - bin.nMax = Position.RightTopFar.Z; - return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin)); -} - -XnStatus XnSensorDepthGenerator::GetUserPosition(XnUInt32 nIndex, XnBoundingBox3D& Position) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get - XnDepthAGCBin bin; - bin.nBin = nIndex; - nRetVal = m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin)); - XN_IS_STATUS_OK(nRetVal); - - XnMapOutputMode MapOutputMode; - nRetVal = GetMapOutputMode(MapOutputMode); - XN_IS_STATUS_OK(nRetVal); - - // we only support Z position for now - Position.LeftBottomNear.Z = bin.nMin; - Position.RightTopFar.Z = bin.nMax; - Position.LeftBottomNear.X = 0; - Position.RightTopFar.X = MapOutputMode.nXRes - 1; - Position.LeftBottomNear.Y = 0; - Position.RightTopFar.Y = MapOutputMode.nYRes - 1; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthGenerator::RegisterToUserPositionChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_AGC_BIN, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorDepthGenerator::UnregisterFromUserPositionChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -XnBool XnSensorDepthGenerator::IsSensorImageNode(xn::ProductionNode& OtherNode) -{ - xn::NodeInfo info = OtherNode.GetInfo(); - - XnVersion Version; - Version.nMajor = XN_PS_MAJOR_VERSION; - Version.nMinor = XN_PS_MINOR_VERSION; - Version.nMaintenance = XN_PS_MAINTENANCE_VERSION; - Version.nBuild = XN_PS_BUILD_VERSION; - - // check if this view point is image from this DLL - if (info.GetDescription().Type != XN_NODE_TYPE_IMAGE || - strcmp(info.GetDescription().strName, XN_DEVICE_NAME) != 0 || - strcmp(info.GetDescription().strVendor, XN_VENDOR_PRIMESENSE) != 0 || - xnVersionCompare(&info.GetDescription().Version, &Version) != 0) - { - return FALSE; - } - - // check if it uses the same device - xn::NodeInfoList needed = info.GetNeededNodes(); - for (xn::NodeInfoList::Iterator it = needed.Begin(); it != needed.End(); ++it) - { - if ((*it).GetDescription().Type == XN_NODE_TYPE_DEVICE && - strcmp((*it).GetCreationInfo(), m_device.GetInfo().GetCreationInfo()) == 0) - { - return TRUE; - } - } - - return FALSE; -} - -XnBool XnSensorDepthGenerator::IsViewPointSupported(xn::ProductionNode& OtherNode) -{ - return IsSensorImageNode(OtherNode); -} - -XnStatus XnSensorDepthGenerator::SetViewPoint(xn::ProductionNode& OtherNode) -{ - if (IsSensorImageNode(OtherNode)) - { - return SetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, TRUE); - } - else - { - return XN_STATUS_BAD_PARAM; - } -} - -XnStatus XnSensorDepthGenerator::ResetViewPoint() -{ - return SetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, FALSE); -} - -XnBool XnSensorDepthGenerator::IsViewPointAs(xn::ProductionNode& OtherNode) -{ - XnUInt64 nValue = FALSE; - GetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, nValue); - - return (nValue == TRUE && IsSensorImageNode(OtherNode)); -} - -XnStatus XnSensorDepthGenerator::RegisterToViewPointChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_REGISTRATION, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorDepthGenerator::UnregisterFromViewPointChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -XnBool XnSensorDepthGenerator::CanFrameSyncWith(xn::ProductionNode& OtherNode) -{ - return (IsSensorImageNode(OtherNode)); -} - -XnStatus XnSensorDepthGenerator::FrameSyncWith(xn::ProductionNode& OtherNode) -{ - if (IsSensorImageNode(OtherNode)) - { - return m_pSensor->SetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)TRUE); - } - else - { - return XN_STATUS_BAD_PARAM; - } -} - -XnStatus XnSensorDepthGenerator::StopFrameSyncWith(xn::ProductionNode& OtherNode) -{ - return m_pSensor->SetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)FALSE); -} - -XnBool XnSensorDepthGenerator::IsFrameSyncedWith(xn::ProductionNode& OtherNode) -{ - XnUInt64 nValue = FALSE; - m_pSensor->GetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, &nValue); - - return (nValue == TRUE && IsSensorImageNode(OtherNode)); -} - -XnStatus XnSensorDepthGenerator::RegisterToFrameSyncChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_MODULE_PROPERTY_FRAME_SYNC, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps, XN_MODULE_NAME_DEVICE); -} - -void XnSensorDepthGenerator::UnregisterFromFrameSyncChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorDepthGenerator::FilterProperties(XnActualPropertiesHash* pHash) -{ - XnSensorMapGenerator::FilterProperties(pHash); - pHash->Remove(XN_STREAM_PROPERTY_REGISTRATION); - pHash->Remove(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH); -} - -//--------------------------------------------------------------------------- -// XnExportedSensorDepthGenerator class -//--------------------------------------------------------------------------- -XnExportedSensorDepthGenerator::XnExportedSensorDepthGenerator() : - XnExportedSensorGenerator(XN_NODE_TYPE_DEPTH, XN_STREAM_TYPE_DEPTH) -{} - -XnSensorGenerator* XnExportedSensorDepthGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) -{ - return XN_NEW(XnSensorDepthGenerator, context, sensor, pSensor, strStreamName); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorDepthGenerator.h" +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// XnSensorDepthGenerator class +//--------------------------------------------------------------------------- + +XnSensorDepthGenerator::XnSensorDepthGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorMapGenerator(context, sensor, pSensor, strStreamName) +{ +} + +XnSensorDepthGenerator::~XnSensorDepthGenerator() +{ + if (m_hRWPropCallback) + { + UnregisterFromProps(m_hRWPropCallback); + } +} + +XnStatus XnSensorDepthGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorMapGenerator::Init(); + XN_IS_STATUS_OK(nRetVal); + + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, + XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, + NULL + }; + + m_hRWPropCallback; + nRetVal = RegisterToProps(RealWorldTranslationPropChanged, this, m_hRWPropCallback, aProps); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = UpdateRealWorldTranslationData(); + if (nRetVal != XN_STATUS_OK) + { + UnregisterFromProps(m_hRWPropCallback); + m_hRWPropCallback = NULL; + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnBool XnSensorDepthGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return (strcmp(strCapabilityName, XN_CAPABILITY_USER_POSITION) == 0 || + strcmp(strCapabilityName, XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) == 0 || + strcmp(strCapabilityName, XN_CAPABILITY_FRAME_SYNC) == 0 || + XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName)); +} + +XnDepthPixel* XnSensorDepthGenerator::GetDepthMap() +{ + return (XnDepthPixel*)m_pStreamData->pData; +} + +XnDepthPixel XnSensorDepthGenerator::GetDeviceMaxDepth() +{ + XnUInt64 nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &nValue); + return (XnDepthPixel)nValue; +} + +void XnSensorDepthGenerator::GetFieldOfView(XnFieldOfView& FOV) +{ + FOV = m_FOV; +} + +XnStatus XnSensorDepthGenerator::RegisterToFieldOfViewChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + return m_fovChangedEvent.Register(handler, pCookie, &hCallback); +} + +void XnSensorDepthGenerator::UnregisterFromFieldOfViewChange(XnCallbackHandle hCallback) +{ + m_fovChangedEvent.Unregister(hCallback); +} + +XnStatus XnSensorDepthGenerator::UpdateRealWorldTranslationData() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt64 nZPD; + nRetVal = GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nZPD); + XN_IS_STATUS_OK(nRetVal); + + XnDouble fZPPS; + nRetVal = GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, fZPPS); + XN_IS_STATUS_OK(nRetVal); + + m_FOV.fHFOV = 2*atan(fZPPS*XN_SXGA_X_RES/2/nZPD); + m_FOV.fVFOV = 2*atan(fZPPS*XN_VGA_Y_RES*2/2/nZPD); + + nRetVal = m_fovChangedEvent.Raise(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnSensorDepthGenerator::RealWorldTranslationPropChanged(void* pCookie) +{ + XnSensorDepthGenerator* pThis = (XnSensorDepthGenerator*)pCookie; + pThis->UpdateRealWorldTranslationData(); +} + +XnUInt32 XnSensorDepthGenerator::GetSupportedUserPositionsCount() +{ + return 4; +} + +XnStatus XnSensorDepthGenerator::SetUserPosition(XnUInt32 nIndex, const XnBoundingBox3D& Position) +{ + // set (we only support Z boxing for now) + XnDepthAGCBin bin; + bin.nBin = nIndex; + bin.nMin = Position.LeftBottomNear.Z; + bin.nMax = Position.RightTopFar.Z; + return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin)); +} + +XnStatus XnSensorDepthGenerator::GetUserPosition(XnUInt32 nIndex, XnBoundingBox3D& Position) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get + XnDepthAGCBin bin; + bin.nBin = nIndex; + nRetVal = m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin)); + XN_IS_STATUS_OK(nRetVal); + + XnMapOutputMode MapOutputMode; + nRetVal = GetMapOutputMode(MapOutputMode); + XN_IS_STATUS_OK(nRetVal); + + // we only support Z position for now + Position.LeftBottomNear.Z = bin.nMin; + Position.RightTopFar.Z = bin.nMax; + Position.LeftBottomNear.X = 0; + Position.RightTopFar.X = MapOutputMode.nXRes - 1; + Position.LeftBottomNear.Y = 0; + Position.RightTopFar.Y = MapOutputMode.nYRes - 1; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthGenerator::RegisterToUserPositionChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_AGC_BIN, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorDepthGenerator::UnregisterFromUserPositionChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +XnBool XnSensorDepthGenerator::IsSensorImageNode(xn::ProductionNode& OtherNode) +{ + xn::NodeInfo info = OtherNode.GetInfo(); + + XnVersion Version; + Version.nMajor = XN_PS_MAJOR_VERSION; + Version.nMinor = XN_PS_MINOR_VERSION; + Version.nMaintenance = XN_PS_MAINTENANCE_VERSION; + Version.nBuild = XN_PS_BUILD_VERSION; + + // check if this view point is image from this DLL + if (info.GetDescription().Type != XN_NODE_TYPE_IMAGE || + strcmp(info.GetDescription().strName, XN_DEVICE_NAME) != 0 || + strcmp(info.GetDescription().strVendor, XN_VENDOR_PRIMESENSE) != 0 || + xnVersionCompare(&info.GetDescription().Version, &Version) != 0) + { + return FALSE; + } + + // check if it uses the same device + xn::NodeInfoList needed = info.GetNeededNodes(); + for (xn::NodeInfoList::Iterator it = needed.Begin(); it != needed.End(); ++it) + { + if ((*it).GetDescription().Type == XN_NODE_TYPE_DEVICE && + strcmp((*it).GetCreationInfo(), m_device.GetInfo().GetCreationInfo()) == 0) + { + return TRUE; + } + } + + return FALSE; +} + +XnBool XnSensorDepthGenerator::IsViewPointSupported(xn::ProductionNode& OtherNode) +{ + return IsSensorImageNode(OtherNode); +} + +XnStatus XnSensorDepthGenerator::SetViewPoint(xn::ProductionNode& OtherNode) +{ + if (IsSensorImageNode(OtherNode)) + { + return SetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, TRUE); + } + else + { + return XN_STATUS_BAD_PARAM; + } +} + +XnStatus XnSensorDepthGenerator::ResetViewPoint() +{ + return SetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, FALSE); +} + +XnBool XnSensorDepthGenerator::IsViewPointAs(xn::ProductionNode& OtherNode) +{ + XnUInt64 nValue = FALSE; + GetIntProperty(XN_STREAM_PROPERTY_REGISTRATION, nValue); + + return (nValue == TRUE && IsSensorImageNode(OtherNode)); +} + +XnStatus XnSensorDepthGenerator::RegisterToViewPointChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_REGISTRATION, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorDepthGenerator::UnregisterFromViewPointChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +XnBool XnSensorDepthGenerator::CanFrameSyncWith(xn::ProductionNode& OtherNode) +{ + return (IsSensorImageNode(OtherNode)); +} + +XnStatus XnSensorDepthGenerator::FrameSyncWith(xn::ProductionNode& OtherNode) +{ + if (IsSensorImageNode(OtherNode)) + { + return m_pSensor->SetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)TRUE); + } + else + { + return XN_STATUS_BAD_PARAM; + } +} + +XnStatus XnSensorDepthGenerator::StopFrameSyncWith(xn::ProductionNode& OtherNode) +{ + return m_pSensor->SetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)FALSE); +} + +XnBool XnSensorDepthGenerator::IsFrameSyncedWith(xn::ProductionNode& OtherNode) +{ + XnUInt64 nValue = FALSE; + m_pSensor->GetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, &nValue); + + return (nValue == TRUE && IsSensorImageNode(OtherNode)); +} + +XnStatus XnSensorDepthGenerator::RegisterToFrameSyncChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_MODULE_PROPERTY_FRAME_SYNC, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps, XN_MODULE_NAME_DEVICE); +} + +void XnSensorDepthGenerator::UnregisterFromFrameSyncChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorDepthGenerator::FilterProperties(XnActualPropertiesHash* pHash) +{ + XnSensorMapGenerator::FilterProperties(pHash); + pHash->Remove(XN_STREAM_PROPERTY_REGISTRATION); + pHash->Remove(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH); +} + +//--------------------------------------------------------------------------- +// XnExportedSensorDepthGenerator class +//--------------------------------------------------------------------------- +XnExportedSensorDepthGenerator::XnExportedSensorDepthGenerator() : + XnExportedSensorGenerator(XN_NODE_TYPE_DEPTH, XN_STREAM_TYPE_DEPTH) +{} + +XnSensorGenerator* XnExportedSensorDepthGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) +{ + return XN_NEW(XnSensorDepthGenerator, context, sensor, pSensor, strStreamName); +} diff --git a/Source/XnDeviceSensorV2/XnSensorDepthGenerator.h b/Source/XnDeviceSensorV2/XnSensorDepthGenerator.h index 33b2ee7..7a395a2 100644 --- a/Source/XnDeviceSensorV2/XnSensorDepthGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorDepthGenerator.h @@ -1,109 +1,109 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_DEPTH_GENERATOR_H__ -#define __XN_SENSOR_DEPTH_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorMapGenerator.h" -#include "XnExportedSensorGenerator.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorDepthGenerator : - public XnSensorMapGenerator, - virtual public xn::ModuleDepthGenerator, - virtual public xn::ModuleUserPositionInterface, - virtual public xn::ModuleAlternativeViewPointInterface, - virtual public xn::ModuleFrameSyncInterface -{ -public: - XnSensorDepthGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - ~XnSensorDepthGenerator(); - - XnStatus Init(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - XnDepthPixel* GetDepthMap(); - XnDepthPixel GetDeviceMaxDepth(); - void GetFieldOfView(XnFieldOfView& FOV); - XnStatus RegisterToFieldOfViewChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromFieldOfViewChange(XnCallbackHandle hCallback); - - xn::ModuleUserPositionInterface* GetUserPositionInterface() { return this; } - XnUInt32 GetSupportedUserPositionsCount(); - XnStatus SetUserPosition(XnUInt32 nIndex, const XnBoundingBox3D& Position); - XnStatus GetUserPosition(XnUInt32 nIndex, XnBoundingBox3D& Position); - XnStatus RegisterToUserPositionChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromUserPositionChange(XnCallbackHandle hCallback); - - xn::ModuleAlternativeViewPointInterface* GetAlternativeViewPointInterface() { return this; } - XnBool IsViewPointSupported(xn::ProductionNode& OtherNode); - XnStatus SetViewPoint(xn::ProductionNode& OtherNode); - XnStatus ResetViewPoint(); - XnBool IsViewPointAs(xn::ProductionNode& OtherNode); - XnStatus RegisterToViewPointChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromViewPointChange(XnCallbackHandle hCallback); - - xn::ModuleFrameSyncInterface* GetFrameSyncInterface() { return this; } - XnBool CanFrameSyncWith(xn::ProductionNode& OtherNode); - XnStatus FrameSyncWith(xn::ProductionNode& OtherNode); - XnStatus StopFrameSyncWith(xn::ProductionNode& OtherNode); - XnBool IsFrameSyncedWith(xn::ProductionNode& OtherNode); - XnStatus RegisterToFrameSyncChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromFrameSyncChange(XnCallbackHandle hCallback); - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); - -private: - XnStatus UpdateRealWorldTranslationData(); - XnBool IsSensorImageNode(xn::ProductionNode& Other); - - static void XN_CALLBACK_TYPE RealWorldTranslationPropChanged(void* pCookie); - - XN_DECLARE_EVENT_0ARG(PropChangeEvent, PropChangeEventInterface); - PropChangeEvent m_fovChangedEvent; - - XnCallbackHandle m_hRWPropCallback; - - XnFieldOfView m_FOV; -}; - -class XnExportedSensorDepthGenerator : public XnExportedSensorGenerator -{ -public: - XnExportedSensorDepthGenerator(); - virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); -}; - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_DEPTH_GENERATOR_H__ +#define __XN_SENSOR_DEPTH_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorMapGenerator.h" +#include "XnExportedSensorGenerator.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorDepthGenerator : + public XnSensorMapGenerator, + virtual public xn::ModuleDepthGenerator, + virtual public xn::ModuleUserPositionInterface, + virtual public xn::ModuleAlternativeViewPointInterface, + virtual public xn::ModuleFrameSyncInterface +{ +public: + XnSensorDepthGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + ~XnSensorDepthGenerator(); + + XnStatus Init(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + XnDepthPixel* GetDepthMap(); + XnDepthPixel GetDeviceMaxDepth(); + void GetFieldOfView(XnFieldOfView& FOV); + XnStatus RegisterToFieldOfViewChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromFieldOfViewChange(XnCallbackHandle hCallback); + + xn::ModuleUserPositionInterface* GetUserPositionInterface() { return this; } + XnUInt32 GetSupportedUserPositionsCount(); + XnStatus SetUserPosition(XnUInt32 nIndex, const XnBoundingBox3D& Position); + XnStatus GetUserPosition(XnUInt32 nIndex, XnBoundingBox3D& Position); + XnStatus RegisterToUserPositionChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromUserPositionChange(XnCallbackHandle hCallback); + + xn::ModuleAlternativeViewPointInterface* GetAlternativeViewPointInterface() { return this; } + XnBool IsViewPointSupported(xn::ProductionNode& OtherNode); + XnStatus SetViewPoint(xn::ProductionNode& OtherNode); + XnStatus ResetViewPoint(); + XnBool IsViewPointAs(xn::ProductionNode& OtherNode); + XnStatus RegisterToViewPointChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromViewPointChange(XnCallbackHandle hCallback); + + xn::ModuleFrameSyncInterface* GetFrameSyncInterface() { return this; } + XnBool CanFrameSyncWith(xn::ProductionNode& OtherNode); + XnStatus FrameSyncWith(xn::ProductionNode& OtherNode); + XnStatus StopFrameSyncWith(xn::ProductionNode& OtherNode); + XnBool IsFrameSyncedWith(xn::ProductionNode& OtherNode); + XnStatus RegisterToFrameSyncChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromFrameSyncChange(XnCallbackHandle hCallback); + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); + +private: + XnStatus UpdateRealWorldTranslationData(); + XnBool IsSensorImageNode(xn::ProductionNode& Other); + + static void XN_CALLBACK_TYPE RealWorldTranslationPropChanged(void* pCookie); + + XN_DECLARE_EVENT_0ARG(PropChangeEvent, PropChangeEventInterface); + PropChangeEvent m_fovChangedEvent; + + XnCallbackHandle m_hRWPropCallback; + + XnFieldOfView m_FOV; +}; + +class XnExportedSensorDepthGenerator : public XnExportedSensorGenerator +{ +public: + XnExportedSensorDepthGenerator(); + virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); +}; + + #endif // __XN_SENSOR_DEPTH_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorDepthStream.cpp b/Source/XnDeviceSensorV2/XnSensorDepthStream.cpp index 06d8827..1ec4645 100644 --- a/Source/XnDeviceSensorV2/XnSensorDepthStream.cpp +++ b/Source/XnDeviceSensorV2/XnSensorDepthStream.cpp @@ -1,955 +1,951 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorInit.h" -#include "XnSensorDepthStream.h" -#include "XnUncompressedDepthProcessor.h" -#include "XnPSCompressedDepthProcessor.h" -#include "XnPacked11DepthProcessor.h" -#include "Registration.h" -#include "XnCmosInfo.h" -#include -#include -#include - - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_DEPTH_STREAM_DEFAULT_INPUT_FORMAT XN_IO_DEPTH_FORMAT_COMPRESSED_PS -#define XN_DEPTH_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA -#define XN_DEPTH_STREAM_DEFAULT_FPS 30 -#define XN_DEPTH_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_DEPTH_VALUES -#define XN_DEPTH_STREAM_DEFAULT_REGISTRATION FALSE -#define XN_DEPTH_STREAM_DEFAULT_REGISTRATION_TYPE XN_PROCESSING_DONT_CARE -#define XN_DEPTH_STREAM_DEFAULT_HOLE_FILLER TRUE -#define XN_DEPTH_STREAM_DEFAULT_WHITE_BALANCE TRUE -#define XN_DEPTH_STREAM_DEFAULT_GAIN_OLD 50 -#define XN_DEPTH_STREAM_DEFAULT_GMC_MODE TRUE - - -#define XN_SHIFTS_MAX_SHIFT 2047 -#define XN_SHIFTS_PIXEL_SIZE_FACTOR 1 -#define XN_SHIFTS_PARAM_COEFFICIENT 4 -#define XN_SHIFTS_SHIFT_SCALE 10 - -#define XN_DEPTH_STREAM_AGC_NUMBER_OF_BINS 4 - -#define XN_DEPTH_MAX_BUFFER_SIZE (XN_VGA_X_RES * XN_VGA_Y_RES * sizeof(XnDepthPixel)) - -//--------------------------------------------------------------------------- -// XnSensorDepthStream class -//--------------------------------------------------------------------------- -XnSensorDepthStream::XnSensorDepthStream(const XnChar* strName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : - XnDepthStream(strName, FALSE, XN_DEVICE_SENSOR_MAX_DEPTH, XN_SHIFTS_MAX_SHIFT), - m_Helper(pObjects), - m_BufferPool(nBufferCount, strName, XN_DEPTH_MAX_BUFFER_SIZE), - m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), - m_InputFormat(XN_STREAM_PROPERTY_INPUT_FORMAT, XN_DEPTH_STREAM_DEFAULT_INPUT_FORMAT), - m_DepthRegistration(XN_STREAM_PROPERTY_REGISTRATION, XN_DEPTH_STREAM_DEFAULT_REGISTRATION), - m_HoleFilter(XN_STREAM_PROPERTY_HOLE_FILTER, XN_DEPTH_STREAM_DEFAULT_HOLE_FILLER), - m_WhiteBalance(XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED, XN_DEPTH_STREAM_DEFAULT_WHITE_BALANCE), - m_Gain(XN_STREAM_PROPERTY_GAIN, XN_DEPTH_STREAM_DEFAULT_GAIN_OLD), - m_RegistrationType(XN_STREAM_PROPERTY_REGISTRATION_TYPE, XN_DEPTH_STREAM_DEFAULT_REGISTRATION_TYPE), - m_AGCBin(XN_STREAM_PROPERTY_AGC_BIN, NULL, ReadAGCBinsFromFile), - m_GMCMode(XN_STREAM_PROPERTY_GMC_MODE, XN_DEPTH_STREAM_DEFAULT_GMC_MODE), - m_FirmwareMirror("FirmwareMirror", FALSE, strName), - m_FirmwareRegistration("FirmwareRegistration", FALSE, strName), - m_FirmwareCropSizeX("FirmwareCropSizeX", 0, strName), - m_FirmwareCropSizeY("FirmwareCropSizeY", 0, strName), - m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, strName), - m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, strName), - m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, strName), - m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE), - m_hReferenceSizeChangedCallback(NULL) -{ - m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); -} - -XnStatus XnSensorDepthStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = SetBufferPool(&m_BufferPool); - XN_IS_STATUS_OK(nRetVal); - - // init base - nRetVal = XnDepthStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - m_InputFormat.UpdateSetCallback(SetInputFormatCallback, this); - m_DepthRegistration.UpdateSetCallback(SetRegistrationCallback, this); - m_HoleFilter.UpdateSetCallback(SetHoleFilterCallback, this); - m_WhiteBalance.UpdateSetCallback(SetWhiteBalanceCallback, this); - m_Gain.UpdateSetCallback(SetGainCallback, this); - m_RegistrationType.UpdateSetCallback(SetRegistrationTypeCallback, this); - m_AGCBin.UpdateSetCallback(SetAGCBinCallback, this); - m_AGCBin.UpdateGetCallback(GetAGCBinCallback, this); - m_GMCMode.UpdateSetCallback(SetGMCModeCallback, this); - - - XN_VALIDATE_ADD_PROPERTIES(this, &m_InputFormat, &m_DepthRegistration, &m_HoleFilter, - &m_WhiteBalance, &m_Gain, &m_AGCBin, &m_SharedBufferName, &m_ActualRead, &m_GMCMode, - &m_RegistrationType, - ); - - // set base properties default values - nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_RESOLUTION); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FPSProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_FPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_OUTPUT_FORMAT); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ParamCoefficientProperty().UnsafeUpdateValue(XN_SHIFTS_PARAM_COEFFICIENT); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ShiftScaleProperty().UnsafeUpdateValue(XN_SHIFTS_SHIFT_SCALE); - XN_IS_STATUS_OK(nRetVal); - - // read some data from firmware - XnDepthInformation DepthInformation; - nRetVal = XnHostProtocolAlgorithmParams(m_Helper.GetPrivateData(), XN_HOST_PROTOCOL_ALGORITHM_DEPTH_INFO, &DepthInformation, sizeof(XnDepthInformation), XN_RESOLUTION_VGA, 30); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ConstShiftProperty().UnsafeUpdateValue(DepthInformation.nConstShift); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ZeroPlaneDistanceProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlaneDistance()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ZeroPlanePixelSizeProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlanePixelSize()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = EmitterDCmosDistanceProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetEmitterDCmosDistance()); - XN_IS_STATUS_OK(nRetVal); - - // init helper - nRetVal = m_Helper.Init(this, this); - XN_IS_STATUS_OK(nRetVal); - - if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_3_0) - { - XN_IS_STATUS_OK(m_GMCMode.UnsafeUpdateValue(FALSE)); - } - - - if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_4_0) - { - XN_IS_STATUS_OK(m_WhiteBalance.UnsafeUpdateValue(FALSE)); - } - - // on old firmwares, the host decides on the default gain. On new firmwares, we read it from firmware - if (m_Helper.GetFirmware()->GetInfo()->nFWVer > XN_SENSOR_FW_VER_1_2) - { - nRetVal = m_Gain.UnsafeUpdateValue(GetFirmwareParams()->m_DepthGain.GetValue()); - XN_IS_STATUS_OK(nRetVal); - } - - // registration - XnCallbackHandle hCallbackDummy; - nRetVal = ResolutionProperty().OnChangeEvent().Register(DecideFirmwareRegistrationCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = DecideFirmwareRegistration((XnBool)m_DepthRegistration.GetValue(), (XnProcessingType)m_RegistrationType.GetValue(), GetResolution()); - XN_IS_STATUS_OK(nRetVal); - - // data processor - nRetVal = m_Helper.RegisterDataProcessorProperty(m_InputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - // pixel size factor - nRetVal = GetFirmwareParams()->m_ReferenceResolution.OnChangeEvent().Register(DecidePixelSizeFactorCallback, this, &m_hReferenceSizeChangedCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = DecidePixelSizeFactor(); - XN_IS_STATUS_OK(nRetVal); - - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::Free() -{ - - m_Registration.Free(); - - // unregister from external properties (internal ones will be destroyed anyway...) - if (m_hReferenceSizeChangedCallback != NULL) - { - GetFirmwareParams()->m_ReferenceResolution.OnChangeEvent().Unregister(m_hReferenceSizeChangedCallback); - m_hReferenceSizeChangedCallback = NULL; - } - - m_Helper.Free(); - - XnDepthStream::Free(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::MapPropertiesToFirmware() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_InputFormat, GetFirmwareParams()->m_DepthFormat, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_DepthResolution, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_DepthFPS, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_HoleFilter, GetFirmwareParams()->m_DepthHoleFilter, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_Gain, GetFirmwareParams()->m_DepthGain, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_WhiteBalance, GetFirmwareParams()->m_DepthWhiteBalance, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareMirror, GetFirmwareParams()->m_DepthMirror, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareRegistration, GetFirmwareParams()->m_RegistrationEnabled, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_DepthCropSizeX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_DepthCropSizeY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_DepthCropOffsetX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_DepthCropOffsetY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_DepthCropEnabled, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_GMCMode, GetFirmwareParams()->m_GMCMode, TRUE)); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::ConfigureStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp); - - nRetVal = SetActualRead(TRUE); - XN_IS_STATUS_OK(nRetVal); - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_InputFormat)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_HoleFilter)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_Gain)); - - // we need to turn decimation on when resolution is QVGA, and FPS is different than 60 - // NOTE: this is ugly as hell. This logic should be moved to firmware. - XnBool bDecimation = (GetResolution() == XN_RESOLUTION_QVGA && GetFPS() != 60); - nRetVal = GetFirmwareParams()->m_DepthDecimation.SetValue(bDecimation); - XN_IS_STATUS_OK(nRetVal); - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareRegistration)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareMirror)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_GMCMode)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_WhiteBalance)); - - nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_DEPTH, GetResolution(), GetFPS()); - XN_IS_STATUS_OK(nRetVal); - - //Turn off the IR projector anti-cover thingy. I find it annoying and It's off on the XBox360 so it must be safe :-) - //This is probably not the best way to do it, but adding it as a real param is too much work for me at the moment... - XnHostProtocolSetParam(GetHelper()->GetPrivateData(), 0x105, 0); - - return XN_STATUS_OK; -} - -XnStatus XnSensorDepthStream::SetActualRead(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_ActualRead.GetValue() != bRead) - { - if (bRead) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB depth read thread..."); - nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificDepthUsb->nChunkReadBytes, XN_SENSOR_USB_DEPTH_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificDepthUsb); - XN_IS_STATUS_OK(nRetVal); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB depth read thread..."); - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp); - } - - nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::OpenStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_DEPTH); - XN_IS_STATUS_OK(nRetVal); - - // Cropping - if (m_FirmwareCropEnabled.GetValue() == TRUE) - { - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); - } - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); - - nRetVal = XnDepthStream::Open(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::CloseStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDepthStream::Close(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetActualRead(FALSE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetOutputFormat(XnOutputFormats nOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_SHIFT_VALUES: - case XN_OUTPUT_FORMAT_DEPTH_VALUES: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported depth output format: %d", nOutputFormat); - } - - nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDepthStream::SetOutputFormat(nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetMirror(XnBool bIsMirrored) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnOSEnterCriticalSection(GetLock()); - - // set firmware mirror - XnBool bFirmwareMirror = (bIsMirrored == TRUE && m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_0); - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareMirror, bFirmwareMirror); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - // update prop - nRetVal = XnDepthStream::SetMirror(bIsMirrored); - xnOSLeaveCriticalSection(GetLock()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetFPS(XnUInt32 nFPS) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDepthStream::SetFPS(nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetResolution(XnResolutions nResolution) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nResolution) - { - case XN_RESOLUTION_QVGA: - case XN_RESOLUTION_VGA: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported depth resolution: %d", nResolution); - } - - nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnDepthStream::SetResolution(nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetInputFormat(XnIODepthFormats nInputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nInputFormat) - { - case XN_IO_DEPTH_FORMAT_COMPRESSED_PS: - case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT: - break; - case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT: - if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_4_0) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_UNSUPPORTED_MODE, XN_MASK_DEVICE_SENSOR, "11-bit depth is not supported on this sensor!"); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown depth input format: %d", nInputFormat); - } - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_InputFormat, nInputFormat); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetRegistration(XnBool bRegistration) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (bRegistration != m_DepthRegistration.GetValue()) - { - nRetVal = DecideFirmwareRegistration(bRegistration, (XnProcessingType)m_RegistrationType.GetValue(), GetResolution()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_DepthRegistration.UnsafeUpdateValue(bRegistration); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetHoleFilter(XnBool bHoleFilter) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_HoleFilter, bHoleFilter); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetWhiteBalance(XnBool bWhiteBalance) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_WhiteBalance, bWhiteBalance); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetGain(XnUInt32 nGain) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_Gain, nGain); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetRegistrationType(XnProcessingType type) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (type != m_RegistrationType.GetValue()) - { - nRetVal = DecideFirmwareRegistration((XnBool)m_DepthRegistration.GetValue(), type, GetResolution()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_RegistrationType.UnsafeUpdateValue(type); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetGMCMode(XnBool bGMCMode) -{ - XnStatus nRetVal = XN_STATUS_OK; - - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_GMCMode, bGMCMode); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensorDepthStream::SetAGCBin(const XnDepthAGCBin* pBin) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_IS_STATUS_OK(ValidateDepthValue(pBin->nMin)); - XN_IS_STATUS_OK(ValidateDepthValue(pBin->nMax)); - - // translate to shifts - XnUInt16* pDepthToShift = GetDepthToShiftTable(); - - XnUInt16 nMinShift = pDepthToShift[pBin->nMin]; - XnUInt16 nMaxShift = pDepthToShift[pBin->nMax]; - - // update firmware - nRetVal = XnHostProtocolSetDepthAGCBin(m_Helper.GetPrivateData(), pBin->nBin, nMinShift, nMaxShift); - XN_IS_STATUS_OK(nRetVal); - - // update prop - nRetVal = m_AGCBin.UnsafeUpdateValue(XnGeneralBufferPack((void*)pBin, sizeof(XnDepthAGCBin))); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::GetAGCBin(XnDepthAGCBin* pBin) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get from firmware - XnUInt16 nMinShift; - XnUInt16 nMaxShift; - - nRetVal = XnHostProtocolGetDepthAGCBin(m_Helper.GetPrivateData(), pBin->nBin, &nMinShift, &nMaxShift); - XN_IS_STATUS_OK(nRetVal); - - // translate to depth - XnDepthPixel* pShiftToDepth = GetShiftToDepthTable(); - - pBin->nMin = pShiftToDepth[nMinShift]; - pBin->nMax = pShiftToDepth[nMaxShift]; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::SetCropping(const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ValidateCropping(pCropping); - XN_IS_STATUS_OK(nRetVal); - - xnOSEnterCriticalSection(GetLock()); - - if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) - { - nRetVal = m_Helper.StartFirmwareTransaction(); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - if (pCropping->bEnabled) - { - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, pCropping->nXOffset); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); - } - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); - - if (nRetVal != XN_STATUS_OK) - { - m_Helper.RollbackFirmwareTransaction(); - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - } - - nRetVal = XnDepthStream::SetCropping(pCropping); - xnOSLeaveCriticalSection(GetLock()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::PostProcessFrame(XnStreamData* pFrameData) -{ - XnBool bPerformRegistration = (GetOutputFormat() == XN_OUTPUT_FORMAT_DEPTH_VALUES && m_DepthRegistration.GetValue() == TRUE && m_FirmwareRegistration.GetValue() == FALSE); - - if (bPerformRegistration) - { - m_Registration.Apply((XnDepthPixel*)pFrameData->pData); - } - - m_Helper.GetFPS()->MarkOutputDepth(pFrameData->nFrameID, pFrameData->nTimestamp); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::ReallocTripleFrameBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (IsOpen()) - { - // before actually replacing buffer, lock the processor (so it will not continue to - // use old buffer) - nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = XnDepthStream::ReallocTripleFrameBuffer(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - return (nRetVal); - } - - if (IsOpen()) - { - nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // if firmware cropping is disabled, crop - if (m_FirmwareCropEnabled.GetValue() == FALSE) - { - nRetVal = XnDepthStream::CropImpl(pStreamOutput, pCropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::Mirror(XnStreamData* pStreamOutput) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - // only perform mirror if it's our job. if mirror is performed by FW, we don't need to do anything. - if (m_FirmwareMirror.GetValue() == FALSE) - { - nRetVal = XnDepthStream::Mirror(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::CreateDataProcessor(XnDataProcessor** ppProcessor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamProcessor* pNew; - - switch (m_InputFormat.GetValue()) - { - case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT: - XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedDepthProcessor, this, &m_Helper); - break; - case XN_IO_DEPTH_FORMAT_COMPRESSED_PS: - XN_VALIDATE_NEW_AND_INIT(pNew, XnPSCompressedDepthProcessor, this, &m_Helper); - break; - case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT: - XN_VALIDATE_NEW_AND_INIT(pNew, XnPacked11DepthProcessor, this, &m_Helper); - break; - default: - return XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT; - } - - *ppProcessor = pNew; - - return XN_STATUS_OK; -} - -XnStatus XnSensorDepthStream::DecideFirmwareRegistration(XnBool bRegistration, XnProcessingType registrationType, XnResolutions nRes) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // start with request - XnBool bFirmwareRegistration = bRegistration; - - if (bFirmwareRegistration) - { - // old chip (PS1000) does not support registration for VGA - XnBool bHardwareRegistrationSupported = - m_Helper.GetPrivateData()->ChipInfo.nChipVer != XN_SENSOR_CHIP_VER_PS1000 || nRes == XN_RESOLUTION_QVGA; - - switch (registrationType) - { - case XN_PROCESSING_HARDWARE: - if (!bHardwareRegistrationSupported) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Sensor does not support hardware registration for current configuration!"); - } - break; - case XN_PROCESSING_SOFTWARE: - if (GetResolution() != XN_RESOLUTION_VGA) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Software registration is only supported for VGA resolution!"); - } - bFirmwareRegistration = FALSE; - break; - case XN_PROCESSING_DONT_CARE: - bFirmwareRegistration = bHardwareRegistrationSupported; - break; - default: - XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown registration type: %d", registrationType); - } - } - - if (bRegistration && !bFirmwareRegistration) - { - // make sure software registration is initialized - if (!m_Registration.IsInitialized()) - { - nRetVal = m_Registration.Init(m_Helper.GetPrivateData(), this, GetDepthToShiftTable()); - XN_IS_STATUS_OK(nRetVal); - } - } - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareRegistration, bFirmwareRegistration); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorDepthStream::DecidePixelSizeFactor() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt32 nPixelSizeFactor; - switch (GetFirmwareParams()->m_ReferenceResolution.GetValue()) - { - case XN_RESOLUTION_SXGA: - nPixelSizeFactor = 1; - break; - case XN_RESOLUTION_VGA: - nPixelSizeFactor = 2; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Can't resolve pixel size for reference resolution %llu", GetFirmwareParams()->m_ReferenceResolution.GetValue()); - } - - if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_3_0) - { - // due to some weird bug (we don't know the reason), DevKits older than 3.0 uses - // a smaller pixel size, but const shift remains the same. To work around this bug, - // we will just update pixel size, instead of updating pixel size factor (so that const - // shift will not be updated) - nRetVal = ZeroPlanePixelSizeProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlanePixelSize() * nPixelSizeFactor); - XN_IS_STATUS_OK(nRetVal); - } - else - { - PixelSizeFactorProperty().UnsafeUpdateValue(nPixelSizeFactor); - } - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetInputFormat((XnIODepthFormats)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetRegistrationCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetRegistration((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetHoleFilterCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetHoleFilter((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetWhiteBalanceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetWhiteBalance((XnBool)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetGainCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetGain((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetRegistrationTypeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetRegistrationType((XnProcessingType)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetGMCModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetGMCMode((XnBool)nValue); -} - - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetAGCBinCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - if (gbValue.nDataSize != sizeof(XnDepthAGCBin)) - { - return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; - } - - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->SetAGCBin((XnDepthAGCBin*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::GetAGCBinCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) -{ - if (gbValue.nDataSize != sizeof(XnDepthAGCBin)) - { - return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; - } - - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->GetAGCBin((XnDepthAGCBin*)gbValue.pData); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorDepthStream* pThis = (XnSensorDepthStream*)pCookie; - return pThis->SetActualRead(nValue == TRUE); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::DecideFirmwareRegistrationCallback(const XnProperty* pSender, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->DecideFirmwareRegistration((XnBool)pStream->m_DepthRegistration.GetValue(), (XnProcessingType)pStream->m_RegistrationType.GetValue(), pStream->GetResolution()); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::DecidePixelSizeFactorCallback(const XnProperty* pSender, void* pCookie) -{ - XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; - return pStream->DecidePixelSizeFactor(); -} - -XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::ReadAGCBinsFromFile(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnUInt32 nBin = 0; nBin < XN_DEPTH_STREAM_AGC_NUMBER_OF_BINS; ++nBin) - { - XnChar csKey[XN_INI_MAX_LEN]; - XnUInt32 nValue; - - XnDepthAGCBin bin; - bin.nBin = nBin; - - XnBool bHasMin = FALSE; - XnBool bHasMax = FALSE; - - sprintf(csKey, "AGCBin%dMinDepth", nBin); - - nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue); - if (nRetVal == XN_STATUS_OK) - { - bin.nMin = nValue; - bHasMin = TRUE; - } - - sprintf(csKey, "AGCBin%dMaxDepth", nBin); - nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue); - if (nRetVal == XN_STATUS_OK) - { - bin.nMax = nValue; - bHasMax = TRUE; - } - - if (bHasMax && bHasMin) - { - nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(bin)); - XN_IS_STATUS_OK(nRetVal); - } - else if (bHasMin || bHasMax) - { - // we have only one - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Bin %d should have both min and max values!", nBin); - } - } - - return XN_STATUS_OK; -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorInit.h" +#include "XnSensorDepthStream.h" +#include "XnUncompressedDepthProcessor.h" +#include "XnPSCompressedDepthProcessor.h" +#include "XnPacked11DepthProcessor.h" +#include "Registration.h" +#include "XnCmosInfo.h" +#include +#include +#include + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_DEPTH_STREAM_DEFAULT_INPUT_FORMAT XN_IO_DEPTH_FORMAT_COMPRESSED_PS +#define XN_DEPTH_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA +#define XN_DEPTH_STREAM_DEFAULT_FPS 30 +#define XN_DEPTH_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_DEPTH_VALUES +#define XN_DEPTH_STREAM_DEFAULT_REGISTRATION FALSE +#define XN_DEPTH_STREAM_DEFAULT_REGISTRATION_TYPE XN_PROCESSING_DONT_CARE +#define XN_DEPTH_STREAM_DEFAULT_HOLE_FILLER TRUE +#define XN_DEPTH_STREAM_DEFAULT_WHITE_BALANCE TRUE +#define XN_DEPTH_STREAM_DEFAULT_GAIN_OLD 50 +#define XN_DEPTH_STREAM_DEFAULT_GMC_MODE TRUE + + +#define XN_SHIFTS_MAX_SHIFT 2047 +#define XN_SHIFTS_PIXEL_SIZE_FACTOR 1 +#define XN_SHIFTS_PARAM_COEFFICIENT 4 +#define XN_SHIFTS_SHIFT_SCALE 10 + +#define XN_DEPTH_STREAM_AGC_NUMBER_OF_BINS 4 + +#define XN_DEPTH_MAX_BUFFER_SIZE (XN_VGA_X_RES * XN_VGA_Y_RES * sizeof(XnDepthPixel)) + +//--------------------------------------------------------------------------- +// XnSensorDepthStream class +//--------------------------------------------------------------------------- +XnSensorDepthStream::XnSensorDepthStream(const XnChar* strDeviceName, const XnChar* strName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : + XnDepthStream(strName, FALSE, XN_DEVICE_SENSOR_MAX_DEPTH, XN_SHIFTS_MAX_SHIFT), + m_Helper(pObjects), + m_BufferPool(nBufferCount, strDeviceName, strName, XN_DEPTH_MAX_BUFFER_SIZE), + m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), + m_InputFormat(XN_STREAM_PROPERTY_INPUT_FORMAT, XN_DEPTH_STREAM_DEFAULT_INPUT_FORMAT), + m_DepthRegistration(XN_STREAM_PROPERTY_REGISTRATION, XN_DEPTH_STREAM_DEFAULT_REGISTRATION), + m_HoleFilter(XN_STREAM_PROPERTY_HOLE_FILTER, XN_DEPTH_STREAM_DEFAULT_HOLE_FILLER), + m_WhiteBalance(XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED, XN_DEPTH_STREAM_DEFAULT_WHITE_BALANCE), + m_Gain(XN_STREAM_PROPERTY_GAIN, XN_DEPTH_STREAM_DEFAULT_GAIN_OLD), + m_RegistrationType(XN_STREAM_PROPERTY_REGISTRATION_TYPE, XN_DEPTH_STREAM_DEFAULT_REGISTRATION_TYPE), + m_AGCBin(XN_STREAM_PROPERTY_AGC_BIN, NULL, ReadAGCBinsFromFile), + m_GMCMode(XN_STREAM_PROPERTY_GMC_MODE, XN_DEPTH_STREAM_DEFAULT_GMC_MODE), + m_FirmwareMirror("FirmwareMirror", FALSE, strName), + m_FirmwareRegistration("FirmwareRegistration", FALSE, strName), + m_FirmwareCropSizeX("FirmwareCropSizeX", 0, strName), + m_FirmwareCropSizeY("FirmwareCropSizeY", 0, strName), + m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, strName), + m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, strName), + m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, strName), + m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE), + m_hReferenceSizeChangedCallback(NULL) +{ + m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); +} + +XnStatus XnSensorDepthStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = SetBufferPool(&m_BufferPool); + XN_IS_STATUS_OK(nRetVal); + + // init base + nRetVal = XnDepthStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + m_InputFormat.UpdateSetCallback(SetInputFormatCallback, this); + m_DepthRegistration.UpdateSetCallback(SetRegistrationCallback, this); + m_HoleFilter.UpdateSetCallback(SetHoleFilterCallback, this); + m_WhiteBalance.UpdateSetCallback(SetWhiteBalanceCallback, this); + m_Gain.UpdateSetCallback(SetGainCallback, this); + m_RegistrationType.UpdateSetCallback(SetRegistrationTypeCallback, this); + m_AGCBin.UpdateSetCallback(SetAGCBinCallback, this); + m_AGCBin.UpdateGetCallback(GetAGCBinCallback, this); + m_GMCMode.UpdateSetCallback(SetGMCModeCallback, this); + + + XN_VALIDATE_ADD_PROPERTIES(this, &m_InputFormat, &m_DepthRegistration, &m_HoleFilter, + &m_WhiteBalance, &m_Gain, &m_AGCBin, &m_SharedBufferName, &m_ActualRead, &m_GMCMode, + &m_RegistrationType, + ); + + // set base properties default values + nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_RESOLUTION); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FPSProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_FPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_DEPTH_STREAM_DEFAULT_OUTPUT_FORMAT); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ParamCoefficientProperty().UnsafeUpdateValue(XN_SHIFTS_PARAM_COEFFICIENT); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ShiftScaleProperty().UnsafeUpdateValue(XN_SHIFTS_SHIFT_SCALE); + XN_IS_STATUS_OK(nRetVal); + + // read some data from firmware + XnDepthInformation DepthInformation; + nRetVal = XnHostProtocolAlgorithmParams(m_Helper.GetPrivateData(), XN_HOST_PROTOCOL_ALGORITHM_DEPTH_INFO, &DepthInformation, sizeof(XnDepthInformation), XN_RESOLUTION_VGA, 30); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ConstShiftProperty().UnsafeUpdateValue(DepthInformation.nConstShift); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ZeroPlaneDistanceProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlaneDistance()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ZeroPlanePixelSizeProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlanePixelSize()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = EmitterDCmosDistanceProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetEmitterDCmosDistance()); + XN_IS_STATUS_OK(nRetVal); + + // init helper + nRetVal = m_Helper.Init(this, this); + XN_IS_STATUS_OK(nRetVal); + + if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_3_0) + { + XN_IS_STATUS_OK(m_GMCMode.UnsafeUpdateValue(FALSE)); + } + + + if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_4_0) + { + XN_IS_STATUS_OK(m_WhiteBalance.UnsafeUpdateValue(FALSE)); + } + + // on old firmwares, the host decides on the default gain. On new firmwares, we read it from firmware + if (m_Helper.GetFirmware()->GetInfo()->nFWVer > XN_SENSOR_FW_VER_1_2) + { + nRetVal = m_Gain.UnsafeUpdateValue(GetFirmwareParams()->m_DepthGain.GetValue()); + XN_IS_STATUS_OK(nRetVal); + } + + // registration + XnCallbackHandle hCallbackDummy; + nRetVal = ResolutionProperty().OnChangeEvent().Register(DecideFirmwareRegistrationCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = DecideFirmwareRegistration((XnBool)m_DepthRegistration.GetValue(), (XnProcessingType)m_RegistrationType.GetValue(), GetResolution()); + XN_IS_STATUS_OK(nRetVal); + + // data processor + nRetVal = m_Helper.RegisterDataProcessorProperty(m_InputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + // pixel size factor + nRetVal = GetFirmwareParams()->m_ReferenceResolution.OnChangeEvent().Register(DecidePixelSizeFactorCallback, this, &m_hReferenceSizeChangedCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = DecidePixelSizeFactor(); + XN_IS_STATUS_OK(nRetVal); + + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::Free() +{ + + m_Registration.Free(); + + // unregister from external properties (internal ones will be destroyed anyway...) + if (m_hReferenceSizeChangedCallback != NULL) + { + GetFirmwareParams()->m_ReferenceResolution.OnChangeEvent().Unregister(m_hReferenceSizeChangedCallback); + m_hReferenceSizeChangedCallback = NULL; + } + + m_Helper.Free(); + + XnDepthStream::Free(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::MapPropertiesToFirmware() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_InputFormat, GetFirmwareParams()->m_DepthFormat, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_DepthResolution, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_DepthFPS, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_HoleFilter, GetFirmwareParams()->m_DepthHoleFilter, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_Gain, GetFirmwareParams()->m_DepthGain, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_WhiteBalance, GetFirmwareParams()->m_DepthWhiteBalance, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareMirror, GetFirmwareParams()->m_DepthMirror, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareRegistration, GetFirmwareParams()->m_RegistrationEnabled, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_DepthCropSizeX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_DepthCropSizeY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_DepthCropOffsetX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_DepthCropOffsetY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_DepthCropEnabled, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_GMCMode, GetFirmwareParams()->m_GMCMode, TRUE)); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::ConfigureStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp); + + nRetVal = SetActualRead(TRUE); + XN_IS_STATUS_OK(nRetVal); + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_InputFormat)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_HoleFilter)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_Gain)); + + // we need to turn decimation on when resolution is QVGA, and FPS is different than 60 + // NOTE: this is ugly as hell. This logic should be moved to firmware. + XnBool bDecimation = (GetResolution() == XN_RESOLUTION_QVGA && GetFPS() != 60); + nRetVal = GetFirmwareParams()->m_DepthDecimation.SetValue(bDecimation); + XN_IS_STATUS_OK(nRetVal); + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareRegistration)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareMirror)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_GMCMode)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_WhiteBalance)); + + nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_DEPTH, GetResolution(), GetFPS()); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_OK; +} + +XnStatus XnSensorDepthStream::SetActualRead(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_ActualRead.GetValue() != bRead) + { + if (bRead) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB depth read thread..."); + nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificDepthUsb->nChunkReadBytes, XN_SENSOR_USB_DEPTH_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificDepthUsb); + XN_IS_STATUS_OK(nRetVal); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB depth read thread..."); + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificDepthUsb->pUsbConnection->UsbEp); + } + + nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::OpenStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_DEPTH); + XN_IS_STATUS_OK(nRetVal); + + // Cropping + if (m_FirmwareCropEnabled.GetValue() == TRUE) + { + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); + } + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); + + nRetVal = XnDepthStream::Open(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::CloseStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream1Mode.SetValue(XN_VIDEO_STREAM_OFF); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDepthStream::Close(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetActualRead(FALSE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetOutputFormat(XnOutputFormats nOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_SHIFT_VALUES: + case XN_OUTPUT_FORMAT_DEPTH_VALUES: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported depth output format: %d", nOutputFormat); + } + + nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDepthStream::SetOutputFormat(nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetMirror(XnBool bIsMirrored) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnOSEnterCriticalSection(GetLock()); + + // set firmware mirror + XnBool bFirmwareMirror = (bIsMirrored == TRUE && m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_0); + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareMirror, bFirmwareMirror); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + // update prop + nRetVal = XnDepthStream::SetMirror(bIsMirrored); + xnOSLeaveCriticalSection(GetLock()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetFPS(XnUInt32 nFPS) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDepthStream::SetFPS(nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetResolution(XnResolutions nResolution) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nResolution) + { + case XN_RESOLUTION_QVGA: + case XN_RESOLUTION_VGA: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported depth resolution: %d", nResolution); + } + + nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnDepthStream::SetResolution(nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetInputFormat(XnIODepthFormats nInputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nInputFormat) + { + case XN_IO_DEPTH_FORMAT_COMPRESSED_PS: + case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT: + break; + case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT: + if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_4_0) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_UNSUPPORTED_MODE, XN_MASK_DEVICE_SENSOR, "11-bit depth is not supported on this sensor!"); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown depth input format: %d", nInputFormat); + } + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_InputFormat, nInputFormat); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetRegistration(XnBool bRegistration) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (bRegistration != m_DepthRegistration.GetValue()) + { + nRetVal = DecideFirmwareRegistration(bRegistration, (XnProcessingType)m_RegistrationType.GetValue(), GetResolution()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_DepthRegistration.UnsafeUpdateValue(bRegistration); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetHoleFilter(XnBool bHoleFilter) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_HoleFilter, bHoleFilter); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetWhiteBalance(XnBool bWhiteBalance) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_WhiteBalance, bWhiteBalance); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetGain(XnUInt32 nGain) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_Gain, nGain); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetRegistrationType(XnProcessingType type) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (type != m_RegistrationType.GetValue()) + { + nRetVal = DecideFirmwareRegistration((XnBool)m_DepthRegistration.GetValue(), type, GetResolution()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_RegistrationType.UnsafeUpdateValue(type); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetGMCMode(XnBool bGMCMode) +{ + XnStatus nRetVal = XN_STATUS_OK; + + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_GMCMode, bGMCMode); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensorDepthStream::SetAGCBin(const XnDepthAGCBin* pBin) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_IS_STATUS_OK(ValidateDepthValue(pBin->nMin)); + XN_IS_STATUS_OK(ValidateDepthValue(pBin->nMax)); + + // translate to shifts + XnUInt16* pDepthToShift = GetDepthToShiftTable(); + + XnUInt16 nMinShift = pDepthToShift[pBin->nMin]; + XnUInt16 nMaxShift = pDepthToShift[pBin->nMax]; + + // update firmware + nRetVal = XnHostProtocolSetDepthAGCBin(m_Helper.GetPrivateData(), pBin->nBin, nMinShift, nMaxShift); + XN_IS_STATUS_OK(nRetVal); + + // update prop + nRetVal = m_AGCBin.UnsafeUpdateValue(XnGeneralBufferPack((void*)pBin, sizeof(XnDepthAGCBin))); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::GetAGCBin(XnDepthAGCBin* pBin) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get from firmware + XnUInt16 nMinShift; + XnUInt16 nMaxShift; + + nRetVal = XnHostProtocolGetDepthAGCBin(m_Helper.GetPrivateData(), pBin->nBin, &nMinShift, &nMaxShift); + XN_IS_STATUS_OK(nRetVal); + + // translate to depth + XnDepthPixel* pShiftToDepth = GetShiftToDepthTable(); + + pBin->nMin = pShiftToDepth[nMinShift]; + pBin->nMax = pShiftToDepth[nMaxShift]; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::SetCropping(const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ValidateCropping(pCropping); + XN_IS_STATUS_OK(nRetVal); + + xnOSEnterCriticalSection(GetLock()); + + if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) + { + nRetVal = m_Helper.StartFirmwareTransaction(); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + if (pCropping->bEnabled) + { + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, pCropping->nXOffset); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); + } + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); + + if (nRetVal != XN_STATUS_OK) + { + m_Helper.RollbackFirmwareTransaction(); + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + } + + nRetVal = XnDepthStream::SetCropping(pCropping); + xnOSLeaveCriticalSection(GetLock()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::PostProcessFrame(XnStreamData* pFrameData) +{ + XnBool bPerformRegistration = (GetOutputFormat() == XN_OUTPUT_FORMAT_DEPTH_VALUES && m_DepthRegistration.GetValue() == TRUE && m_FirmwareRegistration.GetValue() == FALSE); + + if (bPerformRegistration) + { + m_Registration.Apply((XnDepthPixel*)pFrameData->pData); + } + + m_Helper.GetFPS()->MarkOutputDepth(pFrameData->nFrameID, pFrameData->nTimestamp); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::ReallocTripleFrameBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (IsOpen()) + { + // before actually replacing buffer, lock the processor (so it will not continue to + // use old buffer) + nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = XnDepthStream::ReallocTripleFrameBuffer(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + return (nRetVal); + } + + if (IsOpen()) + { + nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // if firmware cropping is disabled, crop + if (m_FirmwareCropEnabled.GetValue() == FALSE) + { + nRetVal = XnDepthStream::CropImpl(pStreamOutput, pCropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::Mirror(XnStreamData* pStreamOutput) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + // only perform mirror if it's our job. if mirror is performed by FW, we don't need to do anything. + if (m_FirmwareMirror.GetValue() == FALSE) + { + nRetVal = XnDepthStream::Mirror(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::CreateDataProcessor(XnDataProcessor** ppProcessor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamProcessor* pNew; + + switch (m_InputFormat.GetValue()) + { + case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_16_BIT: + XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedDepthProcessor, this, &m_Helper); + break; + case XN_IO_DEPTH_FORMAT_COMPRESSED_PS: + XN_VALIDATE_NEW_AND_INIT(pNew, XnPSCompressedDepthProcessor, this, &m_Helper); + break; + case XN_IO_DEPTH_FORMAT_UNCOMPRESSED_11_BIT: + XN_VALIDATE_NEW_AND_INIT(pNew, XnPacked11DepthProcessor, this, &m_Helper); + break; + default: + return XN_STATUS_IO_INVALID_STREAM_DEPTH_FORMAT; + } + + *ppProcessor = pNew; + + return XN_STATUS_OK; +} + +XnStatus XnSensorDepthStream::DecideFirmwareRegistration(XnBool bRegistration, XnProcessingType registrationType, XnResolutions nRes) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // start with request + XnBool bFirmwareRegistration = bRegistration; + + if (bFirmwareRegistration) + { + // old chip (PS1000) does not support registration for VGA + XnBool bHardwareRegistrationSupported = + m_Helper.GetPrivateData()->ChipInfo.nChipVer != XN_SENSOR_CHIP_VER_PS1000 || nRes == XN_RESOLUTION_QVGA; + + switch (registrationType) + { + case XN_PROCESSING_HARDWARE: + if (!bHardwareRegistrationSupported) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Sensor does not support hardware registration for current configuration!"); + } + break; + case XN_PROCESSING_SOFTWARE: + if (GetResolution() != XN_RESOLUTION_VGA) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Software registration is only supported for VGA resolution!"); + } + bFirmwareRegistration = FALSE; + break; + case XN_PROCESSING_DONT_CARE: + bFirmwareRegistration = bHardwareRegistrationSupported; + break; + default: + XN_LOG_ERROR_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown registration type: %d", registrationType); + } + } + + if (bRegistration && !bFirmwareRegistration) + { + // make sure software registration is initialized + if (!m_Registration.IsInitialized()) + { + nRetVal = m_Registration.Init(m_Helper.GetPrivateData(), this, GetDepthToShiftTable()); + XN_IS_STATUS_OK(nRetVal); + } + } + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareRegistration, bFirmwareRegistration); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorDepthStream::DecidePixelSizeFactor() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nPixelSizeFactor; + switch (GetFirmwareParams()->m_ReferenceResolution.GetValue()) + { + case XN_RESOLUTION_SXGA: + nPixelSizeFactor = 1; + break; + case XN_RESOLUTION_VGA: + nPixelSizeFactor = 2; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Can't resolve pixel size for reference resolution %llu", GetFirmwareParams()->m_ReferenceResolution.GetValue()); + } + + if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_3_0) + { + // due to some weird bug (we don't know the reason), DevKits older than 3.0 uses + // a smaller pixel size, but const shift remains the same. To work around this bug, + // we will just update pixel size, instead of updating pixel size factor (so that const + // shift will not be updated) + nRetVal = ZeroPlanePixelSizeProperty().UnsafeUpdateValue(m_Helper.GetFixedParams()->GetZeroPlanePixelSize() * nPixelSizeFactor); + XN_IS_STATUS_OK(nRetVal); + } + else + { + PixelSizeFactorProperty().UnsafeUpdateValue(nPixelSizeFactor); + } + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetInputFormat((XnIODepthFormats)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetRegistrationCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetRegistration((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetHoleFilterCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetHoleFilter((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetWhiteBalanceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetWhiteBalance((XnBool)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetGainCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetGain((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetRegistrationTypeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetRegistrationType((XnProcessingType)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetGMCModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetGMCMode((XnBool)nValue); +} + + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetAGCBinCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + if (gbValue.nDataSize != sizeof(XnDepthAGCBin)) + { + return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; + } + + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->SetAGCBin((XnDepthAGCBin*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::GetAGCBinCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie) +{ + if (gbValue.nDataSize != sizeof(XnDepthAGCBin)) + { + return XN_STATUS_DEVICE_PROPERTY_SIZE_DONT_MATCH; + } + + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->GetAGCBin((XnDepthAGCBin*)gbValue.pData); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorDepthStream* pThis = (XnSensorDepthStream*)pCookie; + return pThis->SetActualRead(nValue == TRUE); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::DecideFirmwareRegistrationCallback(const XnProperty* pSender, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->DecideFirmwareRegistration((XnBool)pStream->m_DepthRegistration.GetValue(), (XnProcessingType)pStream->m_RegistrationType.GetValue(), pStream->GetResolution()); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::DecidePixelSizeFactorCallback(const XnProperty* pSender, void* pCookie) +{ + XnSensorDepthStream* pStream = (XnSensorDepthStream*)pCookie; + return pStream->DecidePixelSizeFactor(); +} + +XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::ReadAGCBinsFromFile(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnUInt32 nBin = 0; nBin < XN_DEPTH_STREAM_AGC_NUMBER_OF_BINS; ++nBin) + { + XnChar csKey[XN_INI_MAX_LEN]; + XnUInt32 nValue; + + XnDepthAGCBin bin; + bin.nBin = nBin; + + XnBool bHasMin = FALSE; + XnBool bHasMax = FALSE; + + sprintf(csKey, "AGCBin%dMinDepth", nBin); + + nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue); + if (nRetVal == XN_STATUS_OK) + { + bin.nMin = nValue; + bHasMin = TRUE; + } + + sprintf(csKey, "AGCBin%dMaxDepth", nBin); + nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue); + if (nRetVal == XN_STATUS_OK) + { + bin.nMax = nValue; + bHasMax = TRUE; + } + + if (bHasMax && bHasMin) + { + nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(bin)); + XN_IS_STATUS_OK(nRetVal); + } + else if (bHasMin || bHasMax) + { + // we have only one + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Bin %d should have both min and max values!", nBin); + } + } + + return XN_STATUS_OK; +} diff --git a/Source/XnDeviceSensorV2/XnSensorDepthStream.h b/Source/XnDeviceSensorV2/XnSensorDepthStream.h index 198e61b..c1487d6 100644 --- a/Source/XnDeviceSensorV2/XnSensorDepthStream.h +++ b/Source/XnDeviceSensorV2/XnSensorDepthStream.h @@ -1,155 +1,155 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_DEPTH_STREAM_H__ -#define __XN_SENSOR_DEPTH_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnDeviceSensorProtocol.h" -#include "Registration.h" -#include "XnSensorStreamHelper.h" -#include "XnSharedMemoryBufferPool.h" - - -//--------------------------------------------------------------------------- -// XnSensorDepthStream class -//--------------------------------------------------------------------------- -class XnSensorDepthStream : public XnDepthStream, public IXnSensorStream -{ -public: - XnSensorDepthStream(const XnChar* strName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); - ~XnSensorDepthStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } - - inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } - - friend class XnDepthProcessor; - -protected: - inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Open() { return m_Helper.Open(); } - XnStatus Close() { return m_Helper.Close(); } - XnStatus PostProcessFrame(XnStreamData* pFrameData); - XnStatus ReallocTripleFrameBuffer(); - XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); - XnStatus Mirror(XnStreamData* pStreamOutput) const; - XnStatus ConfigureStreamImpl(); - XnStatus OpenStreamImpl(); - XnStatus CloseStreamImpl(); - XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); - XnStatus MapPropertiesToFirmware(); - void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } - XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } - XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } - - -protected: - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); - XnStatus SetMirror(XnBool bIsMirrored); - XnStatus SetResolution(XnResolutions nResolution); - XnStatus SetFPS(XnUInt32 nFPS); - virtual XnStatus SetInputFormat(XnIODepthFormats nInputFormat); - virtual XnStatus SetRegistration(XnBool bRegistration); - virtual XnStatus SetHoleFilter(XnBool bHoleFilter); - virtual XnStatus SetWhiteBalance(XnBool bWhiteBalance); - virtual XnStatus SetGain(XnUInt32 nGain); - virtual XnStatus SetRegistrationType(XnProcessingType type); - virtual XnStatus SetAGCBin(const XnDepthAGCBin* pBin); - virtual XnStatus GetAGCBin(XnDepthAGCBin* pBin); - XnStatus SetCropping(const XnCropping* pCropping); - XnStatus SetActualRead(XnBool bRead); - virtual XnStatus SetGMCMode(XnBool bGMCMode); - - -private: - XnUInt32 CalculateExpectedSize(); - XnStatus DecideFirmwareRegistration(XnBool bRegistration, XnProcessingType registrationType, XnResolutions nRes); - XnStatus DecidePixelSizeFactor(); - - static XnStatus XN_CALLBACK_TYPE SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetRegistrationCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetHoleFilterCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetWhiteBalanceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetGainCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetRegistrationTypeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetAGCBinCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE GetAGCBinCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE DecideFirmwareRegistrationCallback(const XnProperty* pSender, void* pCookie); - static XnStatus XN_CALLBACK_TYPE DecidePixelSizeFactorCallback(const XnProperty* pSender, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ReadAGCBinsFromFile(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); - static XnStatus XN_CALLBACK_TYPE SetGMCModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnSensorStreamHelper m_Helper; - XnSharedMemoryBufferPool m_BufferPool; - - XnActualStringProperty m_SharedBufferName; - XnActualIntProperty m_InputFormat; - XnActualIntProperty m_DepthRegistration; - XnActualIntProperty m_HoleFilter; - XnActualIntProperty m_WhiteBalance; - XnActualIntProperty m_Gain; - XnActualIntProperty m_RegistrationType; - XnGeneralProperty m_AGCBin; - - XnActualIntProperty m_FirmwareMirror; - XnActualIntProperty m_FirmwareRegistration; - - XnActualIntProperty m_FirmwareCropSizeX; - XnActualIntProperty m_FirmwareCropSizeY; - XnActualIntProperty m_FirmwareCropOffsetX; - XnActualIntProperty m_FirmwareCropOffsetY; - XnActualIntProperty m_FirmwareCropEnabled; - - XnActualIntProperty m_ActualRead; - XnActualIntProperty m_GMCMode; - - - XnRegistration m_Registration; - XnCallbackHandle m_hReferenceSizeChangedCallback; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_DEPTH_STREAM_H__ +#define __XN_SENSOR_DEPTH_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnDeviceSensorProtocol.h" +#include "Registration.h" +#include "XnSensorStreamHelper.h" +#include "XnSharedMemoryBufferPool.h" + + +//--------------------------------------------------------------------------- +// XnSensorDepthStream class +//--------------------------------------------------------------------------- +class XnSensorDepthStream : public XnDepthStream, public IXnSensorStream +{ +public: + XnSensorDepthStream(const XnChar* strDeviceName, const XnChar* strName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); + ~XnSensorDepthStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } + + inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } + + friend class XnDepthProcessor; + +protected: + inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Open() { return m_Helper.Open(); } + XnStatus Close() { return m_Helper.Close(); } + XnStatus PostProcessFrame(XnStreamData* pFrameData); + XnStatus ReallocTripleFrameBuffer(); + XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); + XnStatus Mirror(XnStreamData* pStreamOutput) const; + XnStatus ConfigureStreamImpl(); + XnStatus OpenStreamImpl(); + XnStatus CloseStreamImpl(); + XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); + XnStatus MapPropertiesToFirmware(); + void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } + XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } + XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } + + +protected: + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); + XnStatus SetMirror(XnBool bIsMirrored); + XnStatus SetResolution(XnResolutions nResolution); + XnStatus SetFPS(XnUInt32 nFPS); + virtual XnStatus SetInputFormat(XnIODepthFormats nInputFormat); + virtual XnStatus SetRegistration(XnBool bRegistration); + virtual XnStatus SetHoleFilter(XnBool bHoleFilter); + virtual XnStatus SetWhiteBalance(XnBool bWhiteBalance); + virtual XnStatus SetGain(XnUInt32 nGain); + virtual XnStatus SetRegistrationType(XnProcessingType type); + virtual XnStatus SetAGCBin(const XnDepthAGCBin* pBin); + virtual XnStatus GetAGCBin(XnDepthAGCBin* pBin); + XnStatus SetCropping(const XnCropping* pCropping); + XnStatus SetActualRead(XnBool bRead); + virtual XnStatus SetGMCMode(XnBool bGMCMode); + + +private: + XnUInt32 CalculateExpectedSize(); + XnStatus DecideFirmwareRegistration(XnBool bRegistration, XnProcessingType registrationType, XnResolutions nRes); + XnStatus DecidePixelSizeFactor(); + + static XnStatus XN_CALLBACK_TYPE SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetRegistrationCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetHoleFilterCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetWhiteBalanceCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetGainCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetRegistrationTypeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetAGCBinCallback(XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE GetAGCBinCallback(const XnGeneralProperty* pSender, const XnGeneralBuffer& gbValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE DecideFirmwareRegistrationCallback(const XnProperty* pSender, void* pCookie); + static XnStatus XN_CALLBACK_TYPE DecidePixelSizeFactorCallback(const XnProperty* pSender, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ReadAGCBinsFromFile(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection); + static XnStatus XN_CALLBACK_TYPE SetGMCModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnSensorStreamHelper m_Helper; + XnSharedMemoryBufferPool m_BufferPool; + + XnActualStringProperty m_SharedBufferName; + XnActualIntProperty m_InputFormat; + XnActualIntProperty m_DepthRegistration; + XnActualIntProperty m_HoleFilter; + XnActualIntProperty m_WhiteBalance; + XnActualIntProperty m_Gain; + XnActualIntProperty m_RegistrationType; + XnGeneralProperty m_AGCBin; + + XnActualIntProperty m_FirmwareMirror; + XnActualIntProperty m_FirmwareRegistration; + + XnActualIntProperty m_FirmwareCropSizeX; + XnActualIntProperty m_FirmwareCropSizeY; + XnActualIntProperty m_FirmwareCropOffsetX; + XnActualIntProperty m_FirmwareCropOffsetY; + XnActualIntProperty m_FirmwareCropEnabled; + + XnActualIntProperty m_ActualRead; + XnActualIntProperty m_GMCMode; + + + XnRegistration m_Registration; + XnCallbackHandle m_hReferenceSizeChangedCallback; +}; + #endif //__XN_SENSOR_DEPTH_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorDevice.cpp b/Source/XnDeviceSensorV2/XnSensorDevice.cpp index cce8aae..70ca6db 100644 --- a/Source/XnDeviceSensorV2/XnSensorDevice.cpp +++ b/Source/XnDeviceSensorV2/XnSensorDevice.cpp @@ -1,75 +1,75 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorDevice.h" - -//--------------------------------------------------------------------------- -// XnSensorDevice class -//--------------------------------------------------------------------------- -XnSensorDevice::XnSensorDevice(xn::Context& context, XnDeviceBase* pSensor, const XnChar* strInstanceName) : - XnSensorProductionNode(context, strInstanceName, pSensor, XN_MODULE_NAME_DEVICE) -{ -} - -XnSensorDevice::~XnSensorDevice() -{ -} - -XnBool XnSensorDevice::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return (strcmp(strCapabilityName, XN_CAPABILITY_ERROR_STATE) == 0 || - XnSensorProductionNode::IsCapabilitySupported(strCapabilityName)); -} - -XnStatus XnSensorDevice::GetErrorState() -{ - XnUInt64 nValue = XN_STATUS_OK; - - XnStatus nRetVal = GetIntProperty(XN_MODULE_PROPERTY_ERROR_STATE, nValue); - XN_ASSERT(nRetVal == XN_STATUS_OK); - - return (XnStatus)nValue; -} - -XnStatus XnSensorDevice::RegisterToErrorStateChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_MODULE_PROPERTY_ERROR_STATE, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorDevice::UnregisterFromErrorStateChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorDevice.h" + +//--------------------------------------------------------------------------- +// XnSensorDevice class +//--------------------------------------------------------------------------- +XnSensorDevice::XnSensorDevice(xn::Context& context, XnDeviceBase* pSensor, const XnChar* strInstanceName) : + XnSensorProductionNode(context, strInstanceName, pSensor, XN_MODULE_NAME_DEVICE) +{ +} + +XnSensorDevice::~XnSensorDevice() +{ +} + +XnBool XnSensorDevice::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return (strcmp(strCapabilityName, XN_CAPABILITY_ERROR_STATE) == 0 || + XnSensorProductionNode::IsCapabilitySupported(strCapabilityName)); +} + +XnStatus XnSensorDevice::GetErrorState() +{ + XnUInt64 nValue = XN_STATUS_OK; + + XnStatus nRetVal = GetIntProperty(XN_MODULE_PROPERTY_ERROR_STATE, nValue); + XN_ASSERT(nRetVal == XN_STATUS_OK); + + return (XnStatus)nValue; +} + +XnStatus XnSensorDevice::RegisterToErrorStateChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_MODULE_PROPERTY_ERROR_STATE, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorDevice::UnregisterFromErrorStateChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} diff --git a/Source/XnDeviceSensorV2/XnSensorDevice.h b/Source/XnDeviceSensorV2/XnSensorDevice.h index 5a8098e..4ff5ded 100644 --- a/Source/XnDeviceSensorV2/XnSensorDevice.h +++ b/Source/XnDeviceSensorV2/XnSensorDevice.h @@ -1,56 +1,56 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_DEVICE_H__ -#define __XN_SENSOR_DEVICE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorProductionNode.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorDevice : - public XnSensorProductionNode, - virtual public xn::ModuleDevice, - virtual public xn::ModuleErrorStateInterface -{ -public: - XnSensorDevice(xn::Context& context, XnDeviceBase* pSensor, const XnChar* strInstanceName); - virtual ~XnSensorDevice(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - virtual ModuleErrorStateInterface* GetErrorStateInterface() { return this; } - virtual XnStatus GetErrorState(); - virtual XnStatus RegisterToErrorStateChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - virtual void UnregisterFromErrorStateChange(XnCallbackHandle hCallback); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_DEVICE_H__ +#define __XN_SENSOR_DEVICE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorProductionNode.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorDevice : + public XnSensorProductionNode, + virtual public xn::ModuleDevice, + virtual public xn::ModuleErrorStateInterface +{ +public: + XnSensorDevice(xn::Context& context, XnDeviceBase* pSensor, const XnChar* strInstanceName); + virtual ~XnSensorDevice(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + virtual ModuleErrorStateInterface* GetErrorStateInterface() { return this; } + virtual XnStatus GetErrorState(); + virtual XnStatus RegisterToErrorStateChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + virtual void UnregisterFromErrorStateChange(XnCallbackHandle hCallback); +}; + #endif // __XN_SENSOR_DEVICE_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorFPS.cpp b/Source/XnDeviceSensorV2/XnSensorFPS.cpp index f6d8a05..933e61d 100644 --- a/Source/XnDeviceSensorV2/XnSensorFPS.cpp +++ b/Source/XnDeviceSensorV2/XnSensorFPS.cpp @@ -1,88 +1,88 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFPS.h" -#include "XnDeviceSensor.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -/* The number of frames to average FPS over */ -#define XN_SENSOR_FPS_FRAME_COUNT 180 - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSensorFPS::XnSensorFPS() : - m_FramesDump(XN_DUMP_CLOSED) -{ - xnFPSInit(&m_InputDepth, XN_SENSOR_FPS_FRAME_COUNT); - xnFPSInit(&m_InputImage, XN_SENSOR_FPS_FRAME_COUNT); - xnFPSInit(&m_ReadCalls, XN_SENSOR_FPS_FRAME_COUNT); - xnFPSInit(&m_OutputDepth, XN_SENSOR_FPS_FRAME_COUNT); - xnFPSInit(&m_OutputImage, XN_SENSOR_FPS_FRAME_COUNT); - - xnDumpInit(&m_FramesDump, XN_MASK_SENSOR_FPS, "TS,Type,FrameID,FrameTS\n", "FramesTimes.csv"); -} - -XnSensorFPS::~XnSensorFPS() -{ - xnFPSFree(&m_InputDepth); - xnFPSFree(&m_InputImage); - xnFPSFree(&m_ReadCalls); - xnFPSFree(&m_OutputDepth); - xnFPSFree(&m_OutputImage); - - xnDumpClose(&m_FramesDump); -} - -void XnSensorFPS::Mark(XnFPSData* pFPS, const XnChar* csName, XnUInt32 nFrameID, XnUInt64 nTS) -{ - if (!xnLogIsEnabled(XN_MASK_SENSOR_FPS, XN_LOG_VERBOSE)) - return; - - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - - xnFPSMarkFrame(pFPS, nNow); - - xnDumpWriteString(m_FramesDump, "%llu,%s,%u,%llu\n", nNow, csName, nFrameID, nTS); - - // get current time in seconds - nNow /= 1000000; - - if (nNow != m_nLastPrint) - { - m_nLastPrint = nNow; - xnLogVerbose(XN_MASK_SENSOR_FPS, "[FPS] InputFrames - I: %5.2f, D: %5.2f, OutputFrames - I: %5.2f, D: %5.2f", - xnFPSCalc(&m_InputImage), xnFPSCalc(&m_InputDepth), xnFPSCalc(&m_OutputImage), xnFPSCalc(&m_OutputDepth)); - } -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFPS.h" +#include "XnDeviceSensor.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +/* The number of frames to average FPS over */ +#define XN_SENSOR_FPS_FRAME_COUNT 180 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensorFPS::XnSensorFPS() : + m_FramesDump(XN_DUMP_CLOSED) +{ + xnFPSInit(&m_InputDepth, XN_SENSOR_FPS_FRAME_COUNT); + xnFPSInit(&m_InputImage, XN_SENSOR_FPS_FRAME_COUNT); + xnFPSInit(&m_ReadCalls, XN_SENSOR_FPS_FRAME_COUNT); + xnFPSInit(&m_OutputDepth, XN_SENSOR_FPS_FRAME_COUNT); + xnFPSInit(&m_OutputImage, XN_SENSOR_FPS_FRAME_COUNT); + + xnDumpInit(&m_FramesDump, XN_MASK_SENSOR_FPS, "TS,Type,FrameID,FrameTS\n", "FramesTimes.csv"); +} + +XnSensorFPS::~XnSensorFPS() +{ + xnFPSFree(&m_InputDepth); + xnFPSFree(&m_InputImage); + xnFPSFree(&m_ReadCalls); + xnFPSFree(&m_OutputDepth); + xnFPSFree(&m_OutputImage); + + xnDumpClose(&m_FramesDump); +} + +void XnSensorFPS::Mark(XnFPSData* pFPS, const XnChar* csName, XnUInt32 nFrameID, XnUInt64 nTS) +{ + if (!xnLogIsEnabled(XN_MASK_SENSOR_FPS, XN_LOG_VERBOSE)) + return; + + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + + xnFPSMarkFrame(pFPS, nNow); + + xnDumpWriteString(m_FramesDump, "%llu,%s,%u,%llu\n", nNow, csName, nFrameID, nTS); + + // get current time in seconds + nNow /= 1000000; + + if (nNow != m_nLastPrint) + { + m_nLastPrint = nNow; + xnLogVerbose(XN_MASK_SENSOR_FPS, "[FPS] InputFrames - I: %5.2f, D: %5.2f, OutputFrames - I: %5.2f, D: %5.2f", + xnFPSCalc(&m_InputImage), xnFPSCalc(&m_InputDepth), xnFPSCalc(&m_OutputImage), xnFPSCalc(&m_OutputDepth)); + } +} diff --git a/Source/XnDeviceSensorV2/XnSensorFPS.h b/Source/XnDeviceSensorV2/XnSensorFPS.h index 2ba26af..556a7c8 100644 --- a/Source/XnDeviceSensorV2/XnSensorFPS.h +++ b/Source/XnDeviceSensorV2/XnSensorFPS.h @@ -1,69 +1,69 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_FPS_H__ -#define __XN_SENSOR_FPS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_MASK_SENSOR_FPS "FramesTimes" - -//--------------------------------------------------------------------------- -// XnSensorFPS class -//--------------------------------------------------------------------------- -class XnSensorFPS -{ -public: - XnSensorFPS(); - ~XnSensorFPS(); - - inline void MarkInputDepth(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_InputDepth, "DepthInput", nFrameID, nTS); } - inline void MarkInputImage(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_InputImage, "ImageInput", nFrameID, nTS); } - inline void MarkReadCalled() { Mark(&m_ReadCalls, "ReadCalled", 0, 0); } - inline void MarkOutputDepth(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_OutputDepth, "DepthOutput", nFrameID, nTS); } - inline void MarkOutputImage(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_OutputImage, "ImageOutput", nFrameID, nTS); } - -private: - void Mark(XnFPSData* pFPS, const XnChar* csName, XnUInt32 nFrameID, XnUInt64 nTS); - - XnFPSData m_InputDepth; - XnFPSData m_InputImage; - XnFPSData m_ReadCalls; - XnFPSData m_OutputDepth; - XnFPSData m_OutputImage; - - XnUInt64 m_nLastPrint; - XnDump m_FramesDump; -}; - -#endif //__XN_SENSOR_FPS_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_FPS_H__ +#define __XN_SENSOR_FPS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MASK_SENSOR_FPS "FramesTimes" + +//--------------------------------------------------------------------------- +// XnSensorFPS class +//--------------------------------------------------------------------------- +class XnSensorFPS +{ +public: + XnSensorFPS(); + ~XnSensorFPS(); + + inline void MarkInputDepth(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_InputDepth, "DepthInput", nFrameID, nTS); } + inline void MarkInputImage(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_InputImage, "ImageInput", nFrameID, nTS); } + inline void MarkReadCalled() { Mark(&m_ReadCalls, "ReadCalled", 0, 0); } + inline void MarkOutputDepth(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_OutputDepth, "DepthOutput", nFrameID, nTS); } + inline void MarkOutputImage(XnUInt32 nFrameID, XnUInt64 nTS) { Mark(&m_OutputImage, "ImageOutput", nFrameID, nTS); } + +private: + void Mark(XnFPSData* pFPS, const XnChar* csName, XnUInt32 nFrameID, XnUInt64 nTS); + + XnFPSData m_InputDepth; + XnFPSData m_InputImage; + XnFPSData m_ReadCalls; + XnFPSData m_OutputDepth; + XnFPSData m_OutputImage; + + XnUInt64 m_nLastPrint; + XnDump m_FramesDump; +}; + +#endif //__XN_SENSOR_FPS_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorFirmware.cpp b/Source/XnDeviceSensorV2/XnSensorFirmware.cpp index 8df69f4..7416733 100644 --- a/Source/XnDeviceSensorV2/XnSensorFirmware.cpp +++ b/Source/XnDeviceSensorV2/XnSensorFirmware.cpp @@ -1,138 +1,138 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFirmware.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSensorFirmware::XnSensorFirmware(XnDevicePrivateData* pDevicePrivateData) : - m_pInfo(&pDevicePrivateData->FWInfo), - m_Commands(pDevicePrivateData), - m_Params(m_pInfo, &m_Commands), - m_Streams(pDevicePrivateData), - m_pDevicePrivateData(pDevicePrivateData) -{ -} - -XnStatus XnSensorFirmware::Init(XnBool bReset) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check current mode - XnUInt16 nMode; - nRetVal = XnHostProtocolGetMode(m_pDevicePrivateData, nMode); - XN_IS_STATUS_OK(nRetVal); - - if (bReset) - { - // check if safe mode - if (nMode == XN_HOST_PROTOCOL_MODE_SAFE_MODE) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_SAFE_MODE, XN_MASK_DEVICE_SENSOR, "Device is in safe mode. Cannot start any stream!"); - } - - // check if device is alive - XnUInt32 nCounter = 5; - while (nCounter) - { - nRetVal = XnHostProtocolKeepAlive(m_pDevicePrivateData); - if (nRetVal != XN_STATUS_OK) - { - nCounter--; - } - else - nCounter = 0; - } - if (nRetVal != XN_STATUS_OK) - { - printf("Keep alive failed!\n"); - return nRetVal; - } - - // perform a soft reset (to start clean) - nRetVal = XnHostProtocolReset(m_pDevicePrivateData, XN_RESET_TYPE_SOFT_FIRST); - if (nRetVal != XN_STATUS_OK) - { - printf("Couldn't reset the device!\n"); - return nRetVal; - } - - // wait for sensor to recover from reset - xnOSSleep(m_pDevicePrivateData->FWInfo.nUSBDelaySoftReset); - - // send keep alive again to see sensor is up - nCounter = 10; - while (nCounter) - { - nRetVal = XnHostProtocolKeepAlive(m_pDevicePrivateData); - if (nRetVal != XN_STATUS_OK) - { - nCounter--; - xnOSSleep(10); - } - else - break; - } - if (nCounter == 0) - { - printf("10 keep alives is too much - stopping\n"); - return nRetVal; - } - - nRetVal = XnHostProtocolGetMode(m_pDevicePrivateData, nMode); - XN_IS_STATUS_OK(nRetVal); - - // check if safe mode - if (nMode == XN_HOST_PROTOCOL_MODE_SAFE_MODE) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_SAFE_MODE, XN_MASK_DEVICE_SENSOR, "Device is in safe mode. Cannot start any stream!"); - } - } - - nRetVal = m_Params.Init(); - XN_IS_STATUS_OK(nRetVal); - - if (nMode == XN_HOST_PROTOCOL_MODE_PS) - { - nRetVal = m_Params.UpdateAllProperties(); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = m_Streams.Init(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnSensorFirmware::Free() -{ - m_Params.Free(); +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFirmware.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensorFirmware::XnSensorFirmware(XnDevicePrivateData* pDevicePrivateData) : + m_pInfo(&pDevicePrivateData->FWInfo), + m_Commands(pDevicePrivateData), + m_Params(m_pInfo, &m_Commands), + m_Streams(pDevicePrivateData), + m_pDevicePrivateData(pDevicePrivateData) +{ +} + +XnStatus XnSensorFirmware::Init(XnBool bReset) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check current mode + XnUInt16 nMode; + nRetVal = XnHostProtocolGetMode(m_pDevicePrivateData, nMode); + XN_IS_STATUS_OK(nRetVal); + + if (bReset) + { + // check if safe mode + if (nMode == XN_HOST_PROTOCOL_MODE_SAFE_MODE) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_SAFE_MODE, XN_MASK_DEVICE_SENSOR, "Device is in safe mode. Cannot start any stream!"); + } + + // check if device is alive + XnUInt32 nCounter = 5; + while (nCounter) + { + nRetVal = XnHostProtocolKeepAlive(m_pDevicePrivateData); + if (nRetVal != XN_STATUS_OK) + { + nCounter--; + } + else + nCounter = 0; + } + if (nRetVal != XN_STATUS_OK) + { + printf("Keep alive failed!\n"); + return nRetVal; + } + + // perform a soft reset (to start clean) + nRetVal = XnHostProtocolReset(m_pDevicePrivateData, XN_RESET_TYPE_SOFT_FIRST); + if (nRetVal != XN_STATUS_OK) + { + printf("Couldn't reset the device!\n"); + return nRetVal; + } + + // wait for sensor to recover from reset + xnOSSleep(m_pDevicePrivateData->FWInfo.nUSBDelaySoftReset); + + // send keep alive again to see sensor is up + nCounter = 10; + while (nCounter) + { + nRetVal = XnHostProtocolKeepAlive(m_pDevicePrivateData); + if (nRetVal != XN_STATUS_OK) + { + nCounter--; + xnOSSleep(10); + } + else + break; + } + if (nCounter == 0) + { + printf("10 keep alives is too much - stopping\n"); + return nRetVal; + } + + nRetVal = XnHostProtocolGetMode(m_pDevicePrivateData, nMode); + XN_IS_STATUS_OK(nRetVal); + + // check if safe mode + if (nMode == XN_HOST_PROTOCOL_MODE_SAFE_MODE) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_SAFE_MODE, XN_MASK_DEVICE_SENSOR, "Device is in safe mode. Cannot start any stream!"); + } + } + + nRetVal = m_Params.Init(); + XN_IS_STATUS_OK(nRetVal); + + if (nMode == XN_HOST_PROTOCOL_MODE_PS) + { + nRetVal = m_Params.UpdateAllProperties(); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = m_Streams.Init(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnSensorFirmware::Free() +{ + m_Params.Free(); } \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorFirmware.h b/Source/XnDeviceSensorV2/XnSensorFirmware.h index be41869..a233ad2 100644 --- a/Source/XnDeviceSensorV2/XnSensorFirmware.h +++ b/Source/XnDeviceSensorV2/XnSensorFirmware.h @@ -1,61 +1,61 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_FIRMWARE_H__ -#define __XN_SENSOR_FIRMWARE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFirmwareInfo.h" -#include "XnFirmwareCommands.h" -#include "XnSensorFirmwareParams.h" -#include "XnFirmwareStreams.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorFirmware -{ -public: - XnSensorFirmware(XnDevicePrivateData* pDevicePrivateData); - XnStatus Init(XnBool bReset); - void Free(); - - inline XnFirmwareInfo* GetInfo() { return m_pInfo; } - inline XnFirmwareCommands* GetCommands() { return &m_Commands; } - inline XnSensorFirmwareParams* GetParams() { return &m_Params; } - inline XnFirmwareStreams* GetStreams() { return &m_Streams; } - -private: - XnFirmwareInfo* m_pInfo; - XnFirmwareCommands m_Commands; - XnSensorFirmwareParams m_Params; - XnFirmwareStreams m_Streams; - XnDevicePrivateData* m_pDevicePrivateData; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_FIRMWARE_H__ +#define __XN_SENSOR_FIRMWARE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFirmwareInfo.h" +#include "XnFirmwareCommands.h" +#include "XnSensorFirmwareParams.h" +#include "XnFirmwareStreams.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorFirmware +{ +public: + XnSensorFirmware(XnDevicePrivateData* pDevicePrivateData); + XnStatus Init(XnBool bReset); + void Free(); + + inline XnFirmwareInfo* GetInfo() { return m_pInfo; } + inline XnFirmwareCommands* GetCommands() { return &m_Commands; } + inline XnSensorFirmwareParams* GetParams() { return &m_Params; } + inline XnFirmwareStreams* GetStreams() { return &m_Streams; } + +private: + XnFirmwareInfo* m_pInfo; + XnFirmwareCommands m_Commands; + XnSensorFirmwareParams m_Params; + XnFirmwareStreams m_Streams; + XnDevicePrivateData* m_pDevicePrivateData; +}; + #endif //__XN_SENSOR_FIRMWARE_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorFirmwareParams.cpp b/Source/XnDeviceSensorV2/XnSensorFirmwareParams.cpp index 0617dce..043ed91 100644 --- a/Source/XnDeviceSensorV2/XnSensorFirmwareParams.cpp +++ b/Source/XnDeviceSensorV2/XnSensorFirmwareParams.cpp @@ -1,620 +1,620 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFirmwareParams.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSensorFirmwareParams::XnSensorFirmwareParams(XnFirmwareInfo* pInfo, XnFirmwareCommands* pCommands) : - m_AllFirmwareParams(), - /* Member Name Firmware Param Min Valid Version Max Valid Version Value if wrong version */ - /* ==================== ======================== ===================================== ==================== ==================== ====================== */ - m_FrameSyncEnabled("FrameSync"), - m_RegistrationEnabled("Registration"), - m_Stream0Mode("Stream0Mode"), - m_Stream1Mode("Stream1Mode"), - m_Stream2Mode("Stream2Mode"), - m_AudioStereo("AudioStereo"), - m_AudioSampleRate("AudioSampleRate"), - m_AudioLeftChannelGain("AudioLeftChannelGain"), - m_AudioRightChannelGain("AudioRightChannelGain"), - m_ImageFormat("ImageFormat"), - m_ImageResolution("ImageResolution"), - m_ImageFPS("ImageFPS"), - m_ImageQuality("ImageQuality"), - m_ImageFlickerDetection("ImageFlicker"), - m_ImageCropSizeX("ImageCropSizeX"), - m_ImageCropSizeY("ImageCropSizeY"), - m_ImageCropOffsetX("ImageCropOffsetX"), - m_ImageCropOffsetY("ImageCropOffsetY"), - m_ImageCropEnabled("ImageCropEnabled"), - m_DepthFormat("DepthFormat"), - m_DepthResolution("DepthResolution"), - m_DepthFPS("DepthFPS"), - m_DepthGain("DepthGain"), - m_DepthHoleFilter("DepthHoleFilter"), - m_DepthMirror("DepthMirror"), - m_DepthDecimation("DepthDecimation"), - m_DepthCropSizeX("DepthCropSizeX"), - m_DepthCropSizeY("DepthCropSizeY"), - m_DepthCropOffsetX("DepthCropOffsetX"), - m_DepthCropOffsetY("DepthCropOffsetY"), - m_DepthCropEnabled("DepthCropEnabled"), - m_IRFormat("IRFormat"), - m_IRResolution("IRResolution"), - m_IRFPS("IRFPS"), - m_IRCropSizeX("IRCropSizeX"), - m_IRCropSizeY("IRCropSizeY"), - m_IRCropOffsetX("IRCropOffsetX"), - m_IRCropOffsetY("IRCropOffsetY"), - m_IRCropEnabled("IRCropEnabled"), - m_DepthWhiteBalance("DepthWhiteBalance"), - m_ImageMirror("ImageMirror"), - m_IRMirror("IRMirror"), - m_ReferenceResolution("ReferenceResolution", 0, "Firmware"), - m_GMCMode("GMCMode"), - m_pInfo(pInfo), - m_pCommands(pCommands), - m_bInTransaction(FALSE) -{ - m_ReferenceResolution.SetLogSeverity(XN_LOG_VERBOSE); -} - -XnSensorFirmwareParams::~XnSensorFirmwareParams() -{ -} - -XnStatus XnSensorFirmwareParams::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - /* Property Param MinVersion MaxVersion ValueIfNotSupported */ - /* ====================== ======================================= ==================== ==================== =================== */ - XN_IS_STATUS_OK(AddFirmwareParam( m_FrameSyncEnabled, PARAM_GENERAL_FRAME_SYNC)); - XN_IS_STATUS_OK(AddFirmwareParam( m_RegistrationEnabled, PARAM_GENERAL_REGISTRATION_ENABLE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_Stream0Mode, PARAM_GENERAL_STREAM0_MODE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_Stream1Mode, PARAM_GENERAL_STREAM1_MODE)); - XN_IS_STATUS_OK(AddFirmwareAudioParam(m_Stream2Mode, PARAM_GENERAL_STREAM2_MODE)); - XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioStereo, PARAM_AUDIO_STEREO_MODE)); - XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioSampleRate, PARAM_AUDIO_SAMPLE_RATE)); - XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioLeftChannelGain, PARAM_AUDIO_LEFT_CHANNEL_VOLUME_LEVEL)); - XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioRightChannelGain, PARAM_AUDIO_RIGHT_CHANNEL_VOLUME_LEVEL)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFormat, PARAM_IMAGE_FORMAT)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageResolution, PARAM_IMAGE_RESOLUTION)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFPS, PARAM_IMAGE_FPS)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageQuality, PARAM_IMAGE_QUALITY)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFlickerDetection, PARAM_IMAGE_FLICKER_DETECTION)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropSizeX, PARAM_IMAGE_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropSizeY, PARAM_IMAGE_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropOffsetX, PARAM_IMAGE_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropOffsetY, PARAM_IMAGE_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropEnabled, PARAM_IMAGE_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthFormat, PARAM_DEPTH_FORMAT)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthResolution, PARAM_DEPTH_RESOLUTION)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthFPS, PARAM_DEPTH_FPS)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthGain, PARAM_DEPTH_AGC)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthHoleFilter, PARAM_DEPTH_HOLE_FILTER)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthMirror, PARAM_DEPTH_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthDecimation, PARAM_DEPTH_DECIMATION)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropSizeX, PARAM_DEPTH_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropSizeY, PARAM_DEPTH_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropOffsetX, PARAM_DEPTH_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropOffsetY, PARAM_DEPTH_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropEnabled, PARAM_DEPTH_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRFormat, PARAM_IR_FORMAT)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRResolution, PARAM_IR_RESOLUTION)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRFPS, PARAM_IR_FPS)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropSizeX, PARAM_IR_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropSizeY, PARAM_IR_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropOffsetX, PARAM_IR_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropOffsetY, PARAM_IR_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropEnabled, PARAM_IR_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_DepthWhiteBalance, PARAM_DEPTH_WHITE_BALANCE_ENABLE, XN_SENSOR_FW_VER_4_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_ImageMirror, PARAM_IMAGE_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_IRMirror, PARAM_IR_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - XN_IS_STATUS_OK(AddFirmwareParam( m_GMCMode, PARAM_DEPTH_GMC_MODE, XN_SENSOR_FW_VER_3_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); - - // override some props - m_ImageResolution.UpdateSetCallback(SetImageResolutionCallback, this); - m_ImageFormat.UpdateSetCallback(SetImageFormatCallback, this); - - // register for some interesting changes - XnCallbackHandle hCallbackDummy; - nRetVal = m_Stream0Mode.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Stream1Mode.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_IRResolution.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_DepthFPS.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RecalculateReferenceResolution(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnSensorFirmwareParams::Free() -{ - m_AllFirmwareParams.Clear(); -} - -XnStatus XnSensorFirmwareParams::AddFirmwareParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnFWVer nMaxVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnUInt16 nValueIfNotSupported /* = 0 */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnFirmwareParam param; - param.pProperty = &Property; - param.nFirmwareParam = nFirmwareParam; - param.MinVer = nMinVer; - param.MaxVer = nMaxVer; - param.nValueIfNotSupported = nValueIfNotSupported; - - nRetVal = m_AllFirmwareParams.Set(&Property, param); - XN_IS_STATUS_OK(nRetVal); - - XnChar csNewName[XN_DEVICE_MAX_STRING_LENGTH]; - sprintf(csNewName, "%s (%d)", Property.GetName(), nFirmwareParam); - - Property.UpdateName("Firmware", csNewName); - Property.SetLogSeverity(XN_LOG_VERBOSE); - Property.SetAlwaysSet(TRUE); - Property.UpdateSetCallback(SetFirmwareParamCallback, this); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::AddFirmwareAudioParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer /* = XN_SENSOR_FW_VER_3_0 */, XnFWVer nMaxVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnUInt16 nValueIfNotSupported /* = 0 */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = AddFirmwareParam(Property, nFirmwareParam, nMinVer, nMaxVer, nValueIfNotSupported); - XN_IS_STATUS_OK(nRetVal); - - Property.UpdateSetCallback(SetFirmwareAudioParamCallback, this); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::UpdateAllProperties() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Reading all params from firmware..."); - - for (XnFirmwareParamsHash::Iterator it = m_AllFirmwareParams.begin(); it != m_AllFirmwareParams.end(); ++it) - { - XnFirmwareParam& param = it.Value(); - nRetVal = UpdateProperty(¶m); - XN_IS_STATUS_OK(nRetVal); - } - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Firmware params were updated."); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::StartTransaction() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_bInTransaction) - { - return XN_STATUS_ERROR; - } - - m_bInTransaction = TRUE; - m_Transaction.Clear(); - m_TransactionOrder.Clear(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::CommitTransaction() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bInTransaction) - { - return XN_STATUS_ERROR; - } - - // we are no longer in transaction, even if we fail to commit. - m_bInTransaction = FALSE; - - for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) - { - XnActualIntProperty* pProp = *it; - - XnUInt32 nValue; - nRetVal = m_Transaction.Get(pProp, nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetFirmwareParamImpl(pProp, nValue); - XN_IS_STATUS_OK(nRetVal); - } - - m_Transaction.Clear(); - m_TransactionOrder.Clear(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::CommitTransactionAsBatch() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bInTransaction) - { - return XN_STATUS_ERROR; - } - - // we are no longer in transaction, even if we fail to commit. - m_bInTransaction = FALSE; - - if (m_TransactionOrder.Size() != 0) - { - XnUInt32 nMaxCount = m_TransactionOrder.Size(); - XnInnerParamData* pParams; - XN_VALIDATE_CALLOC(pParams, XnInnerParamData, nMaxCount); - - XnChar strLogMessage[1024]; - XnUInt32 nMaxLength = 1024; - XnUInt32 nLength = 0; - XnUInt32 nChars; - xnOSStrFormat(strLogMessage + nLength, nMaxLength - nLength, &nChars, "Setting firmware params:\n\t"); - nLength += nChars; - - XnUInt32 nCount = 0; - - for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) - { - XnActualIntProperty* pProp = *it; - - XnUInt32 nValue; - nRetVal = m_Transaction.Get(pProp, nValue); - if (nRetVal != XN_STATUS_OK) - { - xnOSFree(pParams); - return (nRetVal); - } - - XnFirmwareParam* pParam; - nRetVal = CheckFirmwareParam(pProp, nValue, &pParam); - if (nRetVal != XN_STATUS_OK) - { - xnOSFree(pParams); - return (nRetVal); - } - - if (pParam != NULL) - { - xnOSStrFormat(strLogMessage + nLength, nMaxLength - nLength, &nChars, "%s = %u\n\t", pProp->GetName(), nValue); - nLength += nChars; - - pParams[nCount].nParam = pParam->nFirmwareParam; - pParams[nCount].nValue = (XnUInt16)nValue; - nCount++; - } - } - - xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "%s", strLogMessage); - - // set all params - nRetVal = m_pCommands->SetMultipleFirmwareParams(pParams, nCount); - xnOSFree(pParams); - XN_IS_STATUS_OK(nRetVal); - - // and update their props - for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) - { - XnActualIntProperty* pProp = *it; - - XnUInt32 nValue; - nRetVal = m_Transaction.Get(pProp, nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = pProp->UnsafeUpdateValue(nValue); - XN_IS_STATUS_OK(nRetVal); - } - } - - m_Transaction.Clear(); - m_TransactionOrder.Clear(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::RollbackTransaction() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (!m_bInTransaction) - { - return XN_STATUS_ERROR; - } - - m_Transaction.Clear(); - m_TransactionOrder.Clear(); - m_bInTransaction = FALSE; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::UpdateProperty(XnFirmwareParam* pParam) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt16 nNewValue; - - // check version - if ((pParam->MinVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer < pParam->MinVer) || - (pParam->MaxVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer > pParam->MaxVer)) - { - // version not supported - nNewValue = pParam->nValueIfNotSupported; - } - else - { - // Read value from firmware - nRetVal = m_pCommands->GetFirmwareParam(pParam->nFirmwareParam, &nNewValue); - XN_IS_STATUS_OK(nRetVal); - } - - // update value if needed - if (nNewValue != pParam->pProperty->GetValue()) - { - // update base (don't call our function, so that it won't update firmware) - nRetVal = pParam->pProperty->UnsafeUpdateValue(nNewValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::SetFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_bInTransaction) - { - nRetVal = m_Transaction.Set(pProperty, (XnUInt32)nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_TransactionOrder.AddLast(pProperty); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nRetVal = SetFirmwareParamImpl(pProperty, nValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::SetFirmwareAudioParam(XnActualIntProperty* pProperty, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check if audio is not supported, and trying to change the value - if (!m_pInfo->bAudioSupported && nValue != pProperty->GetValue()) - { - return (XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER); - } - - nRetVal = SetFirmwareParam(pProperty, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::SetImageResolution(XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nValue) - { - case XN_RESOLUTION_QVGA: - case XN_RESOLUTION_VGA: - break; - case XN_RESOLUTION_SXGA: - // Avin: Removed to enable 1280x1024 Image - /* - if (m_pInfo->nFWVer < XN_SENSOR_FW_VER_5_3) - { - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "Image resolution is not supported by this firmware!"); - } - */ - break; - case XN_RESOLUTION_UXGA: - if (m_pInfo->nFWVer < XN_SENSOR_FW_VER_5_1) - { - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "Image resolution is not supported by this firmware!"); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported image resolution: %d", nValue); - } - - nRetVal = SetFirmwareParam(&m_ImageResolution, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::SetImageFormat(XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (nValue == XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER) - { - nValue = XN_IO_IMAGE_FORMAT_BAYER; - } - - nRetVal = SetFirmwareParam(&m_ImageFormat, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::CheckFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue, XnFirmwareParam** ppParam) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // find the property in the hash - XnFirmwareParam* pParam; - nRetVal = m_AllFirmwareParams.Get(pProperty, pParam); - XN_IS_STATUS_OK(nRetVal); - - *ppParam = NULL; - - // check version - if ((pParam->MinVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer < pParam->MinVer) || - (pParam->MaxVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer > pParam->MaxVer)) - { - // we only raise an error when trying to change the value... - if (nValue != pParam->nValueIfNotSupported) - { - return (XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER); - } - } - else - { - *ppParam = pParam; - } - - return XN_STATUS_OK; -} - -XnStatus XnSensorFirmwareParams::SetFirmwareParamImpl(XnActualIntProperty* pProperty, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnFirmwareParam* pParam; - nRetVal = CheckFirmwareParam(pProperty, nValue, &pParam); - XN_IS_STATUS_OK(nRetVal); - - if (pParam != NULL) - { - // update firmware - nRetVal = m_pCommands->SetFirmwareParam(pParam->nFirmwareParam, (XnUInt16)nValue); - XN_IS_STATUS_OK(nRetVal); - - // update property - nRetVal = pParam->pProperty->UnsafeUpdateValue(nValue); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::SetStreamMode(XnActualIntProperty* pProperty, XnUInt64 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // we require that every change to mode will go through OFF - if (nValue != XN_VIDEO_STREAM_OFF && pProperty->GetValue() != XN_VIDEO_STREAM_OFF) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Firmware stream is already in use!"); - } - - // OK, set it - nRetVal = SetFirmwareParam(pProperty, nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorFirmwareParams::RecalculateReferenceResolution() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // by default, the 1.3 MP reference is used - XnResolutions nRes = XN_RESOLUTION_SXGA; - - // only in the following cases, VGA reference is used: - // 1. Depth is running in 60 FPS - // 2. IR stream is running in QVGA - if ((m_Stream1Mode.GetValue() == XN_VIDEO_STREAM_DEPTH && m_DepthFPS.GetValue() == 60) || - (m_Stream0Mode.GetValue() == XN_VIDEO_STREAM_IR && m_IRResolution.GetValue() == XN_RESOLUTION_QVGA)) - { - nRes = XN_RESOLUTION_VGA; - } - - if (nRes != m_ReferenceResolution.GetValue()) - { - nRetVal = m_ReferenceResolution.UnsafeUpdateValue(nRes); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetFirmwareParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->SetFirmwareParam(pSender, nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetFirmwareAudioParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->SetFirmwareAudioParam(pSender, nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetImageResolutionCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->SetImageResolution(nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetImageFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->SetImageFormat(nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetStreamModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->SetStreamMode(pSender, nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::ReferenceResolutionPropertyValueChanged(const XnProperty* pSender, void* pCookie) -{ - XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; - return pThis->RecalculateReferenceResolution(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFirmwareParams.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensorFirmwareParams::XnSensorFirmwareParams(XnFirmwareInfo* pInfo, XnFirmwareCommands* pCommands) : + m_AllFirmwareParams(), + /* Member Name Firmware Param Min Valid Version Max Valid Version Value if wrong version */ + /* ==================== ======================== ===================================== ==================== ==================== ====================== */ + m_FrameSyncEnabled("FrameSync"), + m_RegistrationEnabled("Registration"), + m_Stream0Mode("Stream0Mode"), + m_Stream1Mode("Stream1Mode"), + m_Stream2Mode("Stream2Mode"), + m_AudioStereo("AudioStereo"), + m_AudioSampleRate("AudioSampleRate"), + m_AudioLeftChannelGain("AudioLeftChannelGain"), + m_AudioRightChannelGain("AudioRightChannelGain"), + m_ImageFormat("ImageFormat"), + m_ImageResolution("ImageResolution"), + m_ImageFPS("ImageFPS"), + m_ImageQuality("ImageQuality"), + m_ImageFlickerDetection("ImageFlicker"), + m_ImageCropSizeX("ImageCropSizeX"), + m_ImageCropSizeY("ImageCropSizeY"), + m_ImageCropOffsetX("ImageCropOffsetX"), + m_ImageCropOffsetY("ImageCropOffsetY"), + m_ImageCropEnabled("ImageCropEnabled"), + m_DepthFormat("DepthFormat"), + m_DepthResolution("DepthResolution"), + m_DepthFPS("DepthFPS"), + m_DepthGain("DepthGain"), + m_DepthHoleFilter("DepthHoleFilter"), + m_DepthMirror("DepthMirror"), + m_DepthDecimation("DepthDecimation"), + m_DepthCropSizeX("DepthCropSizeX"), + m_DepthCropSizeY("DepthCropSizeY"), + m_DepthCropOffsetX("DepthCropOffsetX"), + m_DepthCropOffsetY("DepthCropOffsetY"), + m_DepthCropEnabled("DepthCropEnabled"), + m_IRFormat("IRFormat"), + m_IRResolution("IRResolution"), + m_IRFPS("IRFPS"), + m_IRCropSizeX("IRCropSizeX"), + m_IRCropSizeY("IRCropSizeY"), + m_IRCropOffsetX("IRCropOffsetX"), + m_IRCropOffsetY("IRCropOffsetY"), + m_IRCropEnabled("IRCropEnabled"), + m_DepthWhiteBalance("DepthWhiteBalance"), + m_ImageMirror("ImageMirror"), + m_IRMirror("IRMirror"), + m_ReferenceResolution("ReferenceResolution", 0, "Firmware"), + m_GMCMode("GMCMode"), + m_pInfo(pInfo), + m_pCommands(pCommands), + m_bInTransaction(FALSE) +{ + m_ReferenceResolution.SetLogSeverity(XN_LOG_VERBOSE); +} + +XnSensorFirmwareParams::~XnSensorFirmwareParams() +{ +} + +XnStatus XnSensorFirmwareParams::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + /* Property Param MinVersion MaxVersion ValueIfNotSupported */ + /* ====================== ======================================= ==================== ==================== =================== */ + XN_IS_STATUS_OK(AddFirmwareParam( m_FrameSyncEnabled, PARAM_GENERAL_FRAME_SYNC)); + XN_IS_STATUS_OK(AddFirmwareParam( m_RegistrationEnabled, PARAM_GENERAL_REGISTRATION_ENABLE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_Stream0Mode, PARAM_GENERAL_STREAM0_MODE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_Stream1Mode, PARAM_GENERAL_STREAM1_MODE)); + XN_IS_STATUS_OK(AddFirmwareAudioParam(m_Stream2Mode, PARAM_GENERAL_STREAM2_MODE)); + XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioStereo, PARAM_AUDIO_STEREO_MODE)); + XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioSampleRate, PARAM_AUDIO_SAMPLE_RATE)); + XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioLeftChannelGain, PARAM_AUDIO_LEFT_CHANNEL_VOLUME_LEVEL)); + XN_IS_STATUS_OK(AddFirmwareAudioParam(m_AudioRightChannelGain, PARAM_AUDIO_RIGHT_CHANNEL_VOLUME_LEVEL)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFormat, PARAM_IMAGE_FORMAT)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageResolution, PARAM_IMAGE_RESOLUTION)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFPS, PARAM_IMAGE_FPS)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageQuality, PARAM_IMAGE_QUALITY)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageFlickerDetection, PARAM_IMAGE_FLICKER_DETECTION)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropSizeX, PARAM_IMAGE_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropSizeY, PARAM_IMAGE_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropOffsetX, PARAM_IMAGE_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropOffsetY, PARAM_IMAGE_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageCropEnabled, PARAM_IMAGE_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthFormat, PARAM_DEPTH_FORMAT)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthResolution, PARAM_DEPTH_RESOLUTION)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthFPS, PARAM_DEPTH_FPS)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthGain, PARAM_DEPTH_AGC)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthHoleFilter, PARAM_DEPTH_HOLE_FILTER)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthMirror, PARAM_DEPTH_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthDecimation, PARAM_DEPTH_DECIMATION)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropSizeX, PARAM_DEPTH_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropSizeY, PARAM_DEPTH_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropOffsetX, PARAM_DEPTH_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropOffsetY, PARAM_DEPTH_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthCropEnabled, PARAM_DEPTH_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRFormat, PARAM_IR_FORMAT)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRResolution, PARAM_IR_RESOLUTION)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRFPS, PARAM_IR_FPS)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropSizeX, PARAM_IR_CROP_SIZE_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropSizeY, PARAM_IR_CROP_SIZE_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropOffsetX, PARAM_IR_CROP_OFFSET_X, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropOffsetY, PARAM_IR_CROP_OFFSET_Y, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, 0)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRCropEnabled, PARAM_IR_CROP_ENABLE, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_DepthWhiteBalance, PARAM_DEPTH_WHITE_BALANCE_ENABLE, XN_SENSOR_FW_VER_4_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_ImageMirror, PARAM_IMAGE_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_IRMirror, PARAM_IR_MIRROR, XN_SENSOR_FW_VER_5_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + XN_IS_STATUS_OK(AddFirmwareParam( m_GMCMode, PARAM_DEPTH_GMC_MODE, XN_SENSOR_FW_VER_3_0, XN_SENSOR_FW_VER_UNKNOWN, FALSE)); + + // override some props + m_ImageResolution.UpdateSetCallback(SetImageResolutionCallback, this); + m_ImageFormat.UpdateSetCallback(SetImageFormatCallback, this); + + // register for some interesting changes + XnCallbackHandle hCallbackDummy; + nRetVal = m_Stream0Mode.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Stream1Mode.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_IRResolution.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_DepthFPS.OnChangeEvent().Register(ReferenceResolutionPropertyValueChanged, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RecalculateReferenceResolution(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnSensorFirmwareParams::Free() +{ + m_AllFirmwareParams.Clear(); +} + +XnStatus XnSensorFirmwareParams::AddFirmwareParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnFWVer nMaxVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnUInt16 nValueIfNotSupported /* = 0 */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnFirmwareParam param; + param.pProperty = &Property; + param.nFirmwareParam = nFirmwareParam; + param.MinVer = nMinVer; + param.MaxVer = nMaxVer; + param.nValueIfNotSupported = nValueIfNotSupported; + + nRetVal = m_AllFirmwareParams.Set(&Property, param); + XN_IS_STATUS_OK(nRetVal); + + XnChar csNewName[XN_DEVICE_MAX_STRING_LENGTH]; + sprintf(csNewName, "%s (%d)", Property.GetName(), nFirmwareParam); + + Property.UpdateName("Firmware", csNewName); + Property.SetLogSeverity(XN_LOG_VERBOSE); + Property.SetAlwaysSet(TRUE); + Property.UpdateSetCallback(SetFirmwareParamCallback, this); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::AddFirmwareAudioParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer /* = XN_SENSOR_FW_VER_3_0 */, XnFWVer nMaxVer /* = XN_SENSOR_FW_VER_UNKNOWN */, XnUInt16 nValueIfNotSupported /* = 0 */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = AddFirmwareParam(Property, nFirmwareParam, nMinVer, nMaxVer, nValueIfNotSupported); + XN_IS_STATUS_OK(nRetVal); + + Property.UpdateSetCallback(SetFirmwareAudioParamCallback, this); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::UpdateAllProperties() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Reading all params from firmware..."); + + for (XnFirmwareParamsHash::Iterator it = m_AllFirmwareParams.begin(); it != m_AllFirmwareParams.end(); ++it) + { + XnFirmwareParam& param = it.Value(); + nRetVal = UpdateProperty(¶m); + XN_IS_STATUS_OK(nRetVal); + } + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Firmware params were updated."); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::StartTransaction() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_bInTransaction) + { + return XN_STATUS_ERROR; + } + + m_bInTransaction = TRUE; + m_Transaction.Clear(); + m_TransactionOrder.Clear(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::CommitTransaction() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bInTransaction) + { + return XN_STATUS_ERROR; + } + + // we are no longer in transaction, even if we fail to commit. + m_bInTransaction = FALSE; + + for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) + { + XnActualIntProperty* pProp = *it; + + XnUInt32 nValue; + nRetVal = m_Transaction.Get(pProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetFirmwareParamImpl(pProp, nValue); + XN_IS_STATUS_OK(nRetVal); + } + + m_Transaction.Clear(); + m_TransactionOrder.Clear(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::CommitTransactionAsBatch() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bInTransaction) + { + return XN_STATUS_ERROR; + } + + // we are no longer in transaction, even if we fail to commit. + m_bInTransaction = FALSE; + + if (m_TransactionOrder.Size() != 0) + { + XnUInt32 nMaxCount = m_TransactionOrder.Size(); + XnInnerParamData* pParams; + XN_VALIDATE_CALLOC(pParams, XnInnerParamData, nMaxCount); + + XnChar strLogMessage[1024]; + XnUInt32 nMaxLength = 1024; + XnUInt32 nLength = 0; + XnUInt32 nChars; + xnOSStrFormat(strLogMessage + nLength, nMaxLength - nLength, &nChars, "Setting firmware params:\n\t"); + nLength += nChars; + + XnUInt32 nCount = 0; + + for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) + { + XnActualIntProperty* pProp = *it; + + XnUInt32 nValue; + nRetVal = m_Transaction.Get(pProp, nValue); + if (nRetVal != XN_STATUS_OK) + { + xnOSFree(pParams); + return (nRetVal); + } + + XnFirmwareParam* pParam; + nRetVal = CheckFirmwareParam(pProp, nValue, &pParam); + if (nRetVal != XN_STATUS_OK) + { + xnOSFree(pParams); + return (nRetVal); + } + + if (pParam != NULL) + { + xnOSStrFormat(strLogMessage + nLength, nMaxLength - nLength, &nChars, "%s = %u\n\t", pProp->GetName(), nValue); + nLength += nChars; + + pParams[nCount].nParam = pParam->nFirmwareParam; + pParams[nCount].nValue = (XnUInt16)nValue; + nCount++; + } + } + + xnLogVerbose(XN_MASK_SENSOR_PROTOCOL, "%s", strLogMessage); + + // set all params + nRetVal = m_pCommands->SetMultipleFirmwareParams(pParams, nCount); + xnOSFree(pParams); + XN_IS_STATUS_OK(nRetVal); + + // and update their props + for (XnActualIntPropertyList::Iterator it = m_TransactionOrder.begin(); it != m_TransactionOrder.end(); ++it) + { + XnActualIntProperty* pProp = *it; + + XnUInt32 nValue; + nRetVal = m_Transaction.Get(pProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = pProp->UnsafeUpdateValue(nValue); + XN_IS_STATUS_OK(nRetVal); + } + } + + m_Transaction.Clear(); + m_TransactionOrder.Clear(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::RollbackTransaction() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (!m_bInTransaction) + { + return XN_STATUS_ERROR; + } + + m_Transaction.Clear(); + m_TransactionOrder.Clear(); + m_bInTransaction = FALSE; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::UpdateProperty(XnFirmwareParam* pParam) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt16 nNewValue; + + // check version + if ((pParam->MinVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer < pParam->MinVer) || + (pParam->MaxVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer > pParam->MaxVer)) + { + // version not supported + nNewValue = pParam->nValueIfNotSupported; + } + else + { + // Read value from firmware + nRetVal = m_pCommands->GetFirmwareParam(pParam->nFirmwareParam, &nNewValue); + XN_IS_STATUS_OK(nRetVal); + } + + // update value if needed + if (nNewValue != pParam->pProperty->GetValue()) + { + // update base (don't call our function, so that it won't update firmware) + nRetVal = pParam->pProperty->UnsafeUpdateValue(nNewValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::SetFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_bInTransaction) + { + nRetVal = m_Transaction.Set(pProperty, (XnUInt32)nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_TransactionOrder.AddLast(pProperty); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nRetVal = SetFirmwareParamImpl(pProperty, nValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::SetFirmwareAudioParam(XnActualIntProperty* pProperty, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if audio is not supported, and trying to change the value + if (!m_pInfo->bAudioSupported && nValue != pProperty->GetValue()) + { + return (XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER); + } + + nRetVal = SetFirmwareParam(pProperty, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::SetImageResolution(XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nValue) + { + case XN_RESOLUTION_QVGA: + case XN_RESOLUTION_VGA: + break; + case XN_RESOLUTION_SXGA: + // Avin: Removed to enable 1280x1024 Image + /* + if (m_pInfo->nFWVer < XN_SENSOR_FW_VER_5_3) + { + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "Image resolution is not supported by this firmware!"); + } + */ + break; + case XN_RESOLUTION_UXGA: + if (m_pInfo->nFWVer < XN_SENSOR_FW_VER_5_1) + { + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "Image resolution is not supported by this firmware!"); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported image resolution: %d", nValue); + } + + nRetVal = SetFirmwareParam(&m_ImageResolution, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::SetImageFormat(XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (nValue == XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER) + { + nValue = XN_IO_IMAGE_FORMAT_BAYER; + } + + nRetVal = SetFirmwareParam(&m_ImageFormat, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::CheckFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue, XnFirmwareParam** ppParam) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // find the property in the hash + XnFirmwareParam* pParam; + nRetVal = m_AllFirmwareParams.Get(pProperty, pParam); + XN_IS_STATUS_OK(nRetVal); + + *ppParam = NULL; + + // check version + if ((pParam->MinVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer < pParam->MinVer) || + (pParam->MaxVer != XN_SENSOR_FW_VER_UNKNOWN && m_pInfo->nFWVer > pParam->MaxVer)) + { + // we only raise an error when trying to change the value... + if (nValue != pParam->nValueIfNotSupported) + { + return (XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER); + } + } + else + { + *ppParam = pParam; + } + + return XN_STATUS_OK; +} + +XnStatus XnSensorFirmwareParams::SetFirmwareParamImpl(XnActualIntProperty* pProperty, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnFirmwareParam* pParam; + nRetVal = CheckFirmwareParam(pProperty, nValue, &pParam); + XN_IS_STATUS_OK(nRetVal); + + if (pParam != NULL) + { + // update firmware + nRetVal = m_pCommands->SetFirmwareParam(pParam->nFirmwareParam, (XnUInt16)nValue); + XN_IS_STATUS_OK(nRetVal); + + // update property + nRetVal = pParam->pProperty->UnsafeUpdateValue(nValue); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::SetStreamMode(XnActualIntProperty* pProperty, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // we require that every change to mode will go through OFF + if (nValue != XN_VIDEO_STREAM_OFF && pProperty->GetValue() != XN_VIDEO_STREAM_OFF) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Firmware stream is already in use!"); + } + + // OK, set it + nRetVal = SetFirmwareParam(pProperty, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorFirmwareParams::RecalculateReferenceResolution() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // by default, the 1.3 MP reference is used + XnResolutions nRes = XN_RESOLUTION_SXGA; + + // only in the following cases, VGA reference is used: + // 1. Depth is running in 60 FPS + // 2. IR stream is running in QVGA + if ((m_Stream1Mode.GetValue() == XN_VIDEO_STREAM_DEPTH && m_DepthFPS.GetValue() == 60) || + (m_Stream0Mode.GetValue() == XN_VIDEO_STREAM_IR && m_IRResolution.GetValue() == XN_RESOLUTION_QVGA)) + { + nRes = XN_RESOLUTION_VGA; + } + + if (nRes != m_ReferenceResolution.GetValue()) + { + nRetVal = m_ReferenceResolution.UnsafeUpdateValue(nRes); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetFirmwareParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->SetFirmwareParam(pSender, nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetFirmwareAudioParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->SetFirmwareAudioParam(pSender, nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetImageResolutionCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->SetImageResolution(nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetImageFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->SetImageFormat(nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::SetStreamModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->SetStreamMode(pSender, nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorFirmwareParams::ReferenceResolutionPropertyValueChanged(const XnProperty* pSender, void* pCookie) +{ + XnSensorFirmwareParams* pThis = (XnSensorFirmwareParams*)pCookie; + return pThis->RecalculateReferenceResolution(); +} diff --git a/Source/XnDeviceSensorV2/XnSensorFirmwareParams.h b/Source/XnDeviceSensorV2/XnSensorFirmwareParams.h index 504003e..9e4459b 100644 --- a/Source/XnDeviceSensorV2/XnSensorFirmwareParams.h +++ b/Source/XnDeviceSensorV2/XnSensorFirmwareParams.h @@ -1,154 +1,154 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_FIRMWARE_PARAMS_H__ -#define __XN_SENSOR_FIRMWARE_PARAMS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnParams.h" -#include -#include "XnFirmwareInfo.h" -#include "XnFirmwareCommands.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- - -/** -* Holds all firmware params -*/ -class XnSensorFirmwareParams -{ -public: - XnSensorFirmwareParams(XnFirmwareInfo* pInfo, XnFirmwareCommands* pCommands); - ~XnSensorFirmwareParams(); - - //--------------------------------------------------------------------------- - // Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - void Free(); - XnStatus UpdateAllProperties(); - XnStatus StartTransaction(); - XnStatus CommitTransaction(); - XnStatus CommitTransactionAsBatch(); - XnStatus RollbackTransaction(); - - XnActualIntProperty m_FrameSyncEnabled; - XnActualIntProperty m_RegistrationEnabled; - XnActualIntProperty m_Stream0Mode; - XnActualIntProperty m_Stream1Mode; - XnActualIntProperty m_Stream2Mode; - XnActualIntProperty m_AudioStereo; - XnActualIntProperty m_AudioSampleRate; - XnActualIntProperty m_AudioLeftChannelGain; - XnActualIntProperty m_AudioRightChannelGain; - XnActualIntProperty m_ImageFormat; - XnActualIntProperty m_ImageResolution; - XnActualIntProperty m_ImageFPS; - XnActualIntProperty m_ImageQuality; - XnActualIntProperty m_ImageFlickerDetection; - XnActualIntProperty m_ImageCropSizeX; - XnActualIntProperty m_ImageCropSizeY; - XnActualIntProperty m_ImageCropOffsetX; - XnActualIntProperty m_ImageCropOffsetY; - XnActualIntProperty m_ImageCropEnabled; - XnActualIntProperty m_DepthFormat; - XnActualIntProperty m_DepthResolution; - XnActualIntProperty m_DepthFPS; - XnActualIntProperty m_DepthGain; - XnActualIntProperty m_DepthHoleFilter; - XnActualIntProperty m_DepthMirror; - XnActualIntProperty m_DepthDecimation; - XnActualIntProperty m_DepthCropSizeX; - XnActualIntProperty m_DepthCropSizeY; - XnActualIntProperty m_DepthCropOffsetX; - XnActualIntProperty m_DepthCropOffsetY; - XnActualIntProperty m_DepthCropEnabled; - XnActualIntProperty m_IRFormat; - XnActualIntProperty m_IRResolution; - XnActualIntProperty m_IRFPS; - XnActualIntProperty m_IRCropSizeX; - XnActualIntProperty m_IRCropSizeY; - XnActualIntProperty m_IRCropOffsetX; - XnActualIntProperty m_IRCropOffsetY; - XnActualIntProperty m_IRCropEnabled; - XnActualIntProperty m_ImageMirror; - XnActualIntProperty m_IRMirror; - XnActualIntProperty m_ReferenceResolution; - XnActualIntProperty m_DepthWhiteBalance; - XnActualIntProperty m_GMCMode; - -private: - typedef struct XnFirmwareParam - { - XnActualIntProperty* pProperty; - XnUInt16 nFirmwareParam; - XnFWVer MinVer; - XnFWVer MaxVer; - XnUInt16 nValueIfNotSupported; - } XnFirmwareParam; - - XN_DECLARE_DEFAULT_HASH(XnActualIntProperty*, XnFirmwareParam, XnFirmwareParamsHash) - XN_DECLARE_LIST(XnActualIntProperty*, XnActualIntPropertyList) - XN_DECLARE_DEFAULT_HASH(XnActualIntProperty*, XnUInt32, XnPropertyToValueHash) - - XnStatus AddFirmwareParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer = XN_SENSOR_FW_VER_UNKNOWN, XnFWVer nMaxVer = XN_SENSOR_FW_VER_UNKNOWN, XnUInt16 nValueIfNotSupported = 0); - XnStatus AddFirmwareAudioParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer = XN_SENSOR_FW_VER_3_0, XnFWVer nMaxVer = XN_SENSOR_FW_VER_UNKNOWN, XnUInt16 nValueIfNotSupported = 0); - - XnStatus UpdateProperty(XnFirmwareParam* pParam); - - XnStatus SetFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue); - XnStatus SetFirmwareAudioParam(XnActualIntProperty* pProperty, XnUInt64 nValue); - XnStatus SetImageResolution(XnUInt64 nValue); - XnStatus SetImageFormat(XnUInt64 nValue); - XnStatus SetStreamMode(XnActualIntProperty* pProperty, XnUInt64 nValue); - XnStatus RecalculateReferenceResolution(); - XnStatus GetFirmwareParam(XnActualIntProperty* pProperty, XnFirmwareParam** ppParam); - - XnStatus SetFirmwareParamImpl(XnActualIntProperty* pProperty, XnUInt64 nValue); - XnStatus CheckFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue, XnFirmwareParam** ppParam); - - static XnStatus XN_CALLBACK_TYPE SetFirmwareParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetFirmwareAudioParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetImageResolutionCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetImageFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetStreamModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE ReferenceResolutionPropertyValueChanged(const XnProperty* pSender, void* pCookie); - - XnFirmwareParamsHash m_AllFirmwareParams; - - XnFirmwareInfo* m_pInfo; - XnFirmwareCommands* m_pCommands; - XnBool m_bInTransaction; - XnActualIntPropertyList m_TransactionOrder; // the transaction according to the order in which it was set - XnPropertyToValueHash m_Transaction; // maps a property to its new value -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_FIRMWARE_PARAMS_H__ +#define __XN_SENSOR_FIRMWARE_PARAMS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnParams.h" +#include +#include "XnFirmwareInfo.h" +#include "XnFirmwareCommands.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +/** +* Holds all firmware params +*/ +class XnSensorFirmwareParams +{ +public: + XnSensorFirmwareParams(XnFirmwareInfo* pInfo, XnFirmwareCommands* pCommands); + ~XnSensorFirmwareParams(); + + //--------------------------------------------------------------------------- + // Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + void Free(); + XnStatus UpdateAllProperties(); + XnStatus StartTransaction(); + XnStatus CommitTransaction(); + XnStatus CommitTransactionAsBatch(); + XnStatus RollbackTransaction(); + + XnActualIntProperty m_FrameSyncEnabled; + XnActualIntProperty m_RegistrationEnabled; + XnActualIntProperty m_Stream0Mode; + XnActualIntProperty m_Stream1Mode; + XnActualIntProperty m_Stream2Mode; + XnActualIntProperty m_AudioStereo; + XnActualIntProperty m_AudioSampleRate; + XnActualIntProperty m_AudioLeftChannelGain; + XnActualIntProperty m_AudioRightChannelGain; + XnActualIntProperty m_ImageFormat; + XnActualIntProperty m_ImageResolution; + XnActualIntProperty m_ImageFPS; + XnActualIntProperty m_ImageQuality; + XnActualIntProperty m_ImageFlickerDetection; + XnActualIntProperty m_ImageCropSizeX; + XnActualIntProperty m_ImageCropSizeY; + XnActualIntProperty m_ImageCropOffsetX; + XnActualIntProperty m_ImageCropOffsetY; + XnActualIntProperty m_ImageCropEnabled; + XnActualIntProperty m_DepthFormat; + XnActualIntProperty m_DepthResolution; + XnActualIntProperty m_DepthFPS; + XnActualIntProperty m_DepthGain; + XnActualIntProperty m_DepthHoleFilter; + XnActualIntProperty m_DepthMirror; + XnActualIntProperty m_DepthDecimation; + XnActualIntProperty m_DepthCropSizeX; + XnActualIntProperty m_DepthCropSizeY; + XnActualIntProperty m_DepthCropOffsetX; + XnActualIntProperty m_DepthCropOffsetY; + XnActualIntProperty m_DepthCropEnabled; + XnActualIntProperty m_IRFormat; + XnActualIntProperty m_IRResolution; + XnActualIntProperty m_IRFPS; + XnActualIntProperty m_IRCropSizeX; + XnActualIntProperty m_IRCropSizeY; + XnActualIntProperty m_IRCropOffsetX; + XnActualIntProperty m_IRCropOffsetY; + XnActualIntProperty m_IRCropEnabled; + XnActualIntProperty m_ImageMirror; + XnActualIntProperty m_IRMirror; + XnActualIntProperty m_ReferenceResolution; + XnActualIntProperty m_DepthWhiteBalance; + XnActualIntProperty m_GMCMode; + +private: + typedef struct XnFirmwareParam + { + XnActualIntProperty* pProperty; + XnUInt16 nFirmwareParam; + XnFWVer MinVer; + XnFWVer MaxVer; + XnUInt16 nValueIfNotSupported; + } XnFirmwareParam; + + XN_DECLARE_DEFAULT_HASH(XnActualIntProperty*, XnFirmwareParam, XnFirmwareParamsHash) + XN_DECLARE_LIST(XnActualIntProperty*, XnActualIntPropertyList) + XN_DECLARE_DEFAULT_HASH(XnActualIntProperty*, XnUInt32, XnPropertyToValueHash) + + XnStatus AddFirmwareParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer = XN_SENSOR_FW_VER_UNKNOWN, XnFWVer nMaxVer = XN_SENSOR_FW_VER_UNKNOWN, XnUInt16 nValueIfNotSupported = 0); + XnStatus AddFirmwareAudioParam(XnActualIntProperty& Property, XnUInt16 nFirmwareParam, XnFWVer nMinVer = XN_SENSOR_FW_VER_3_0, XnFWVer nMaxVer = XN_SENSOR_FW_VER_UNKNOWN, XnUInt16 nValueIfNotSupported = 0); + + XnStatus UpdateProperty(XnFirmwareParam* pParam); + + XnStatus SetFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue); + XnStatus SetFirmwareAudioParam(XnActualIntProperty* pProperty, XnUInt64 nValue); + XnStatus SetImageResolution(XnUInt64 nValue); + XnStatus SetImageFormat(XnUInt64 nValue); + XnStatus SetStreamMode(XnActualIntProperty* pProperty, XnUInt64 nValue); + XnStatus RecalculateReferenceResolution(); + XnStatus GetFirmwareParam(XnActualIntProperty* pProperty, XnFirmwareParam** ppParam); + + XnStatus SetFirmwareParamImpl(XnActualIntProperty* pProperty, XnUInt64 nValue); + XnStatus CheckFirmwareParam(XnActualIntProperty* pProperty, XnUInt64 nValue, XnFirmwareParam** ppParam); + + static XnStatus XN_CALLBACK_TYPE SetFirmwareParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetFirmwareAudioParamCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetImageResolutionCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetImageFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetStreamModeCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE ReferenceResolutionPropertyValueChanged(const XnProperty* pSender, void* pCookie); + + XnFirmwareParamsHash m_AllFirmwareParams; + + XnFirmwareInfo* m_pInfo; + XnFirmwareCommands* m_pCommands; + XnBool m_bInTransaction; + XnActualIntPropertyList m_TransactionOrder; // the transaction according to the order in which it was set + XnPropertyToValueHash m_Transaction; // maps a property to its new value +}; + #endif //__XN_SENSOR_FIRMWARE_PARAMS_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorFixedParams.cpp b/Source/XnDeviceSensorV2/XnSensorFixedParams.cpp index e9c8229..eb340f0 100644 --- a/Source/XnDeviceSensorV2/XnSensorFixedParams.cpp +++ b/Source/XnDeviceSensorV2/XnSensorFixedParams.cpp @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFixedParams.h" -#include "XnHostProtocol.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnSensorFixedParams::XnSensorFixedParams(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData) : - m_pFirmware(pFirmware), - m_pDevicePrivateData(pDevicePrivateData) -{ -} - -XnStatus XnSensorFixedParams::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get fixed params - XnFixedParams FixedParams; - nRetVal = XnHostProtocolGetFixedParams(m_pDevicePrivateData, FixedParams); - if (nRetVal != XN_STATUS_OK) - { - } - - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Sensor serial number: %d", FixedParams.nSerialNumber); - - // fill in properties - m_nZeroPlaneDistance = (XnDepthPixel)FixedParams.fReferenceDistance; - m_dZeroPlanePixelSize = FixedParams.fReferencePixelSize; - m_dEmitterDCmosDistance = FixedParams.fDCmosEmitterDistance; - sprintf(m_strSensorSerial, "%x", FixedParams.nSerialNumber); - - - return (XN_STATUS_OK); +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFixedParams.h" +#include "XnHostProtocol.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensorFixedParams::XnSensorFixedParams(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData) : + m_pFirmware(pFirmware), + m_pDevicePrivateData(pDevicePrivateData) +{ +} + +XnStatus XnSensorFixedParams::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get fixed params + XnFixedParams FixedParams; + nRetVal = XnHostProtocolGetFixedParams(m_pDevicePrivateData, FixedParams); + if (nRetVal != XN_STATUS_OK) + { + } + + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Sensor serial number: %d", FixedParams.nSerialNumber); + + // fill in properties + m_nZeroPlaneDistance = (XnDepthPixel)FixedParams.fReferenceDistance; + m_dZeroPlanePixelSize = FixedParams.fReferencePixelSize; + m_dEmitterDCmosDistance = FixedParams.fDCmosEmitterDistance; + sprintf(m_strSensorSerial, "%x", FixedParams.nSerialNumber); + + + return (XN_STATUS_OK); } \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorFixedParams.h b/Source/XnDeviceSensorV2/XnSensorFixedParams.h index 9075a39..40c0cb8 100644 --- a/Source/XnDeviceSensorV2/XnSensorFixedParams.h +++ b/Source/XnDeviceSensorV2/XnSensorFixedParams.h @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_FIXED_PARAMS_H__ -#define __XN_SENSOR_FIXED_PARAMS_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorFirmware.h" - -//--------------------------------------------------------------------------- -// XnSensorFixedParams class -//--------------------------------------------------------------------------- -class XnSensorFixedParams -{ -public: - XnSensorFixedParams(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData); - - XnStatus Init(); - - - inline XnDepthPixel GetZeroPlaneDistance() const { return m_nZeroPlaneDistance; } - inline XnDouble GetZeroPlanePixelSize() const { return m_dZeroPlanePixelSize; } - inline XnDouble GetEmitterDCmosDistance() const { return m_dEmitterDCmosDistance; } - - inline const XnChar* GetSensorSerial() const { return m_strSensorSerial; } - -private: - XnSensorFirmware* m_pFirmware; - XnDevicePrivateData* m_pDevicePrivateData; - - - XnDepthPixel m_nZeroPlaneDistance; - XnDouble m_dZeroPlanePixelSize; - XnDouble m_dEmitterDCmosDistance; - - XnChar m_strSensorSerial[XN_DEVICE_MAX_STRING_LENGTH]; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_FIXED_PARAMS_H__ +#define __XN_SENSOR_FIXED_PARAMS_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorFirmware.h" + +//--------------------------------------------------------------------------- +// XnSensorFixedParams class +//--------------------------------------------------------------------------- +class XnSensorFixedParams +{ +public: + XnSensorFixedParams(XnSensorFirmware* pFirmware, XnDevicePrivateData* pDevicePrivateData); + + XnStatus Init(); + + + inline XnDepthPixel GetZeroPlaneDistance() const { return m_nZeroPlaneDistance; } + inline XnDouble GetZeroPlanePixelSize() const { return m_dZeroPlanePixelSize; } + inline XnDouble GetEmitterDCmosDistance() const { return m_dEmitterDCmosDistance; } + + inline const XnChar* GetSensorSerial() const { return m_strSensorSerial; } + +private: + XnSensorFirmware* m_pFirmware; + XnDevicePrivateData* m_pDevicePrivateData; + + + XnDepthPixel m_nZeroPlaneDistance; + XnDouble m_dZeroPlanePixelSize; + XnDouble m_dEmitterDCmosDistance; + + XnChar m_strSensorSerial[XN_DEVICE_MAX_STRING_LENGTH]; +}; + #endif //__XN_SENSOR_FIXED_PARAMS_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorGenerator.cpp index 8fe2f6e..299bfc0 100644 --- a/Source/XnDeviceSensorV2/XnSensorGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorGenerator.cpp @@ -1,203 +1,203 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorGenerator.h" - -//--------------------------------------------------------------------------- -// XnSensorGenerator class -//--------------------------------------------------------------------------- -XnSensorGenerator::XnSensorGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorProductionNode(context, strStreamName, pSensor, strStreamName), - m_pStreamData(NULL), - m_device(sensor) -{} - -XnSensorGenerator::~XnSensorGenerator() -{ - m_pSensor->DestroyStreamData(&m_pStreamData); -} - -XnStatus XnSensorGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pSensor->GetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_VERSION, XN_PACK_GENERAL_BUFFER(m_Version)); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pSensor->CreateStreamData(m_strModule, &m_pStreamData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnBool XnSensorGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return (strcmp(strCapabilityName, XN_CAPABILITY_MIRROR) == 0 || - XnSensorProductionNode::IsCapabilitySupported(strCapabilityName)); -} - -XnStatus XnSensorGenerator::StartGenerating() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pSensor->OpenStream(m_strModule); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnBool XnSensorGenerator::IsGenerating() -{ - XnUInt64 nValue = FALSE; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_STATE, &nValue); - return (XnBool)nValue; -} - -void XnSensorGenerator::StopGenerating() -{ - m_pSensor->CloseStream(m_strModule); -} - -XnStatus XnSensorGenerator::RegisterToGenerationRunningChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_STATE, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorGenerator::UnregisterFromGenerationRunningChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -XnStatus XnSensorGenerator::RegisterToNewDataAvailable(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - XnStatus nRetVal = XN_STATUS_OK; - NewDataCallback* pNewDataCallback; - XN_VALIDATE_NEW(pNewDataCallback, NewDataCallback, this, handler, pCookie); - hCallback = pNewDataCallback; - nRetVal = m_pSensor->RegisterToNewStreamData(&OnDeviceNewStreamData, pNewDataCallback, &(pNewDataCallback->m_hCallback)); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pNewDataCallback); - return nRetVal; - } - - return XN_STATUS_OK; -} - -void XnSensorGenerator::UnregisterFromNewDataAvailable(XnCallbackHandle hCallback) -{ - NewDataCallback *pNewDataCallback = (NewDataCallback*)hCallback; - m_pSensor->UnregisterFromNewStreamData(pNewDataCallback->m_hCallback); - XN_DELETE(pNewDataCallback); -} - -XnBool XnSensorGenerator::IsNewDataAvailable(XnUInt64& nTimestamp) -{ - XnBool bResult = FALSE; - m_pSensor->IsNewDataAvailable(m_strModule, &bResult, &nTimestamp); - return bResult; -} - -XnStatus XnSensorGenerator::UpdateData() -{ - return m_pSensor->ReadStream(m_pStreamData); -} - -XnUInt32 XnSensorGenerator::GetDataSize() -{ - return m_pStreamData->nDataSize; -} - -XnUInt64 XnSensorGenerator::GetTimestamp() -{ - return m_pStreamData->nTimestamp; -} - -XnUInt32 XnSensorGenerator::GetFrameID() -{ - return m_pStreamData->nFrameID; -} - -XnStatus XnSensorGenerator::SetMirror(XnBool bMirror) -{ - if (bMirror != IsMirrored()) - { - return m_pSensor->SetProperty(m_strModule, XN_MODULE_PROPERTY_MIRROR, (XnUInt64)bMirror); - } - else - { - return (XN_STATUS_OK); - } -} - -XnBool XnSensorGenerator::IsMirrored() -{ - XnUInt64 nValue; - m_pSensor->GetProperty(m_strModule, XN_MODULE_PROPERTY_MIRROR, &nValue); - return (XnBool)nValue; -} - -XnStatus XnSensorGenerator::RegisterToMirrorChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_MODULE_PROPERTY_MIRROR, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorGenerator::UnregisterFromMirrorChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorGenerator::FilterProperties(XnActualPropertiesHash* pHash) -{ - XnSensorProductionNode::FilterProperties(pHash); - pHash->Remove(XN_MODULE_PROPERTY_MIRROR); - pHash->Remove(XN_STREAM_PROPERTY_STATE); -} - -void XN_CALLBACK_TYPE XnSensorGenerator::OnDeviceNewStreamData(XnDeviceHandle pDeviceHandle, const XnChar* StreamName, void* pCookie) -{ - NewDataCallback *pNewDataCBParams = (NewDataCallback*)pCookie; - if (strcmp(pNewDataCBParams->m_pGenerator->m_strInstanceName, StreamName) == 0) - { - pNewDataCBParams->m_handler(pNewDataCBParams->m_pCookie); - } +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorGenerator.h" + +//--------------------------------------------------------------------------- +// XnSensorGenerator class +//--------------------------------------------------------------------------- +XnSensorGenerator::XnSensorGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorProductionNode(context, strStreamName, pSensor, strStreamName), + m_pStreamData(NULL), + m_device(sensor) +{} + +XnSensorGenerator::~XnSensorGenerator() +{ + m_pSensor->DestroyStreamData(&m_pStreamData); +} + +XnStatus XnSensorGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pSensor->GetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_VERSION, XN_PACK_GENERAL_BUFFER(m_Version)); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->CreateStreamData(m_strModule, &m_pStreamData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnBool XnSensorGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return (strcmp(strCapabilityName, XN_CAPABILITY_MIRROR) == 0 || + XnSensorProductionNode::IsCapabilitySupported(strCapabilityName)); +} + +XnStatus XnSensorGenerator::StartGenerating() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pSensor->OpenStream(m_strModule); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnBool XnSensorGenerator::IsGenerating() +{ + XnUInt64 nValue = FALSE; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_STATE, &nValue); + return (XnBool)nValue; +} + +void XnSensorGenerator::StopGenerating() +{ + m_pSensor->CloseStream(m_strModule); +} + +XnStatus XnSensorGenerator::RegisterToGenerationRunningChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_STATE, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorGenerator::UnregisterFromGenerationRunningChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +XnStatus XnSensorGenerator::RegisterToNewDataAvailable(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + NewDataCallback* pNewDataCallback; + XN_VALIDATE_NEW(pNewDataCallback, NewDataCallback, this, handler, pCookie); + hCallback = pNewDataCallback; + nRetVal = m_pSensor->RegisterToNewStreamData(&OnDeviceNewStreamData, pNewDataCallback, &(pNewDataCallback->m_hCallback)); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pNewDataCallback); + return nRetVal; + } + + return XN_STATUS_OK; +} + +void XnSensorGenerator::UnregisterFromNewDataAvailable(XnCallbackHandle hCallback) +{ + NewDataCallback *pNewDataCallback = (NewDataCallback*)hCallback; + m_pSensor->UnregisterFromNewStreamData(pNewDataCallback->m_hCallback); + XN_DELETE(pNewDataCallback); +} + +XnBool XnSensorGenerator::IsNewDataAvailable(XnUInt64& nTimestamp) +{ + XnBool bResult = FALSE; + m_pSensor->IsNewDataAvailable(m_strModule, &bResult, &nTimestamp); + return bResult; +} + +XnStatus XnSensorGenerator::UpdateData() +{ + return m_pSensor->ReadStream(m_pStreamData); +} + +XnUInt32 XnSensorGenerator::GetDataSize() +{ + return m_pStreamData->nDataSize; +} + +XnUInt64 XnSensorGenerator::GetTimestamp() +{ + return m_pStreamData->nTimestamp; +} + +XnUInt32 XnSensorGenerator::GetFrameID() +{ + return m_pStreamData->nFrameID; +} + +XnStatus XnSensorGenerator::SetMirror(XnBool bMirror) +{ + if (bMirror != IsMirrored()) + { + return m_pSensor->SetProperty(m_strModule, XN_MODULE_PROPERTY_MIRROR, (XnUInt64)bMirror); + } + else + { + return (XN_STATUS_OK); + } +} + +XnBool XnSensorGenerator::IsMirrored() +{ + XnUInt64 nValue; + m_pSensor->GetProperty(m_strModule, XN_MODULE_PROPERTY_MIRROR, &nValue); + return (XnBool)nValue; +} + +XnStatus XnSensorGenerator::RegisterToMirrorChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_MODULE_PROPERTY_MIRROR, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorGenerator::UnregisterFromMirrorChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorGenerator::FilterProperties(XnActualPropertiesHash* pHash) +{ + XnSensorProductionNode::FilterProperties(pHash); + pHash->Remove(XN_MODULE_PROPERTY_MIRROR); + pHash->Remove(XN_STREAM_PROPERTY_STATE); +} + +void XN_CALLBACK_TYPE XnSensorGenerator::OnDeviceNewStreamData(XnDeviceHandle pDeviceHandle, const XnChar* StreamName, void* pCookie) +{ + NewDataCallback *pNewDataCBParams = (NewDataCallback*)pCookie; + if (strcmp(pNewDataCBParams->m_pGenerator->m_strInstanceName, StreamName) == 0) + { + pNewDataCBParams->m_handler(pNewDataCBParams->m_pCookie); + } } \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorGenerator.h b/Source/XnDeviceSensorV2/XnSensorGenerator.h index 2b0dd90..1243474 100644 --- a/Source/XnDeviceSensorV2/XnSensorGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorGenerator.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_GENERATOR_H__ -#define __XN_SENSOR_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorProductionNode.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorGenerator : - public XnSensorProductionNode, - virtual public xn::ModuleGenerator, - virtual public xn::ModuleMirrorInterface -{ -public: - XnSensorGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - ~XnSensorGenerator(); - - XnStatus Init(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - XnStatus StartGenerating(); - XnBool IsGenerating(); - void StopGenerating(); - XnStatus RegisterToGenerationRunningChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromGenerationRunningChange(XnCallbackHandle hCallback); - XnStatus RegisterToNewDataAvailable(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromNewDataAvailable(XnCallbackHandle hCallback); - XnBool IsNewDataAvailable(XnUInt64& pnTimestamp); - XnStatus UpdateData(); - XnUInt32 GetDataSize(); - XnUInt64 GetTimestamp(); - XnUInt32 GetFrameID(); - - xn::ModuleMirrorInterface* GetMirrorInterface() { return this; } - XnStatus SetMirror(XnBool bMirror); - XnBool IsMirrored(); - XnStatus RegisterToMirrorChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromMirrorChange(XnCallbackHandle hCallback); - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); - - XnStreamData* m_pStreamData; - XnVersions m_Version; - xn::Device m_device; - -private: - struct NewDataCallback - { - NewDataCallback(XnSensorGenerator *pGenerator, XnModuleStateChangedHandler handler, void *pCookie) : - m_pGenerator(pGenerator), m_handler(handler), m_pCookie(pCookie), m_hCallback(NULL) {} - - XnSensorGenerator *m_pGenerator; - XnModuleStateChangedHandler m_handler; - void *m_pCookie; - XnCallbackHandle m_hCallback; - }; - - static void XN_CALLBACK_TYPE OnDeviceNewStreamData(XnDeviceHandle pDeviceHandle, const XnChar* StreamName, void* pCookie); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_GENERATOR_H__ +#define __XN_SENSOR_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorProductionNode.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorGenerator : + public XnSensorProductionNode, + virtual public xn::ModuleGenerator, + virtual public xn::ModuleMirrorInterface +{ +public: + XnSensorGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + ~XnSensorGenerator(); + + XnStatus Init(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + XnStatus StartGenerating(); + XnBool IsGenerating(); + void StopGenerating(); + XnStatus RegisterToGenerationRunningChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromGenerationRunningChange(XnCallbackHandle hCallback); + XnStatus RegisterToNewDataAvailable(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromNewDataAvailable(XnCallbackHandle hCallback); + XnBool IsNewDataAvailable(XnUInt64& pnTimestamp); + XnStatus UpdateData(); + XnUInt32 GetDataSize(); + XnUInt64 GetTimestamp(); + XnUInt32 GetFrameID(); + + xn::ModuleMirrorInterface* GetMirrorInterface() { return this; } + XnStatus SetMirror(XnBool bMirror); + XnBool IsMirrored(); + XnStatus RegisterToMirrorChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromMirrorChange(XnCallbackHandle hCallback); + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); + + XnStreamData* m_pStreamData; + XnVersions m_Version; + xn::Device m_device; + +private: + struct NewDataCallback + { + NewDataCallback(XnSensorGenerator *pGenerator, XnModuleStateChangedHandler handler, void *pCookie) : + m_pGenerator(pGenerator), m_handler(handler), m_pCookie(pCookie), m_hCallback(NULL) {} + + XnSensorGenerator *m_pGenerator; + XnModuleStateChangedHandler m_handler; + void *m_pCookie; + XnCallbackHandle m_hCallback; + }; + + static void XN_CALLBACK_TYPE OnDeviceNewStreamData(XnDeviceHandle pDeviceHandle, const XnChar* StreamName, void* pCookie); +}; + #endif // __XN_SENSOR_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorIRGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorIRGenerator.cpp index 0e6b093..82c2ebe 100644 --- a/Source/XnDeviceSensorV2/XnSensorIRGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorIRGenerator.cpp @@ -1,125 +1,125 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorIRGenerator.h" -#include - -//--------------------------------------------------------------------------- -// XnSensorIRGenerator class -//--------------------------------------------------------------------------- -XnSensorIRGenerator::XnSensorIRGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorMapGenerator(context, sensor, pSensor, strStreamName), - m_hMapModeCallback(NULL), - m_hCroppingCallback(NULL), - m_nBufferSize(0) -{} - -XnStatus XnSensorIRGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorMapGenerator::Init(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetIntProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, XN_OUTPUT_FORMAT_GRAYSCALE16); - XN_IS_STATUS_OK(nRetVal); - - //Register to map output mode and cropping events - nRetVal = RegisterToMapOutputModeChange(OnResChangedCallback, this, m_hMapModeCallback); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RegisterToCroppingChange(OnResChangedCallback, this, m_hCroppingCallback); - XN_IS_STATUS_OK(nRetVal); - - // add SXGA 30 - XnMapOutputMode mode; - mode.nXRes = XN_SXGA_X_RES; - mode.nYRes = XN_SXGA_Y_RES; - mode.nFPS = 30; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - - OnResChanged(); - - return (XN_STATUS_OK); -} - -XnBool XnSensorIRGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName); -} - -XnIRPixel* XnSensorIRGenerator::GetIRMap() -{ - return (XnIRPixel*)m_pStreamData->pData; -} - -XnUInt32 XnSensorIRGenerator::GetDataSize() -{ - return m_nBufferSize; -} - -void XnSensorIRGenerator::OnResChanged() -{ - // we calculate the size because the IR stream actually gives out a bigger buffer, but - // we want the buffer we return to be with the right size. - XnMapOutputMode outputMode; - GetMapOutputMode(outputMode); - - XnUInt32 nPixels = outputMode.nXRes * outputMode.nYRes; - - XnCropping cropping; - GetCropping(cropping); - - if (cropping.bEnabled) - { - nPixels = cropping.nXSize * cropping.nYSize; - } - - m_nBufferSize = nPixels * sizeof(XnIRPixel); -} - -void XN_CALLBACK_TYPE XnSensorIRGenerator::OnResChangedCallback(void* pCookie) -{ - XnSensorIRGenerator* pThis = (XnSensorIRGenerator*)pCookie; - pThis->OnResChanged(); -} - -//--------------------------------------------------------------------------- -// XnExportedSensorIRGenerator class -//--------------------------------------------------------------------------- -XnExportedSensorIRGenerator::XnExportedSensorIRGenerator() : - XnExportedSensorGenerator(XN_NODE_TYPE_IR, XN_STREAM_TYPE_IR) -{} - -XnSensorGenerator* XnExportedSensorIRGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) -{ - return XN_NEW(XnSensorIRGenerator, context, sensor, pSensor, strStreamName); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorIRGenerator.h" +#include + +//--------------------------------------------------------------------------- +// XnSensorIRGenerator class +//--------------------------------------------------------------------------- +XnSensorIRGenerator::XnSensorIRGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorMapGenerator(context, sensor, pSensor, strStreamName), + m_hMapModeCallback(NULL), + m_hCroppingCallback(NULL), + m_nBufferSize(0) +{} + +XnStatus XnSensorIRGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorMapGenerator::Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetIntProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, XN_OUTPUT_FORMAT_GRAYSCALE16); + XN_IS_STATUS_OK(nRetVal); + + //Register to map output mode and cropping events + nRetVal = RegisterToMapOutputModeChange(OnResChangedCallback, this, m_hMapModeCallback); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RegisterToCroppingChange(OnResChangedCallback, this, m_hCroppingCallback); + XN_IS_STATUS_OK(nRetVal); + + // add SXGA 30 + XnMapOutputMode mode; + mode.nXRes = XN_SXGA_X_RES; + mode.nYRes = XN_SXGA_Y_RES; + mode.nFPS = 30; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + + OnResChanged(); + + return (XN_STATUS_OK); +} + +XnBool XnSensorIRGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName); +} + +XnIRPixel* XnSensorIRGenerator::GetIRMap() +{ + return (XnIRPixel*)m_pStreamData->pData; +} + +XnUInt32 XnSensorIRGenerator::GetDataSize() +{ + return m_nBufferSize; +} + +void XnSensorIRGenerator::OnResChanged() +{ + // we calculate the size because the IR stream actually gives out a bigger buffer, but + // we want the buffer we return to be with the right size. + XnMapOutputMode outputMode; + GetMapOutputMode(outputMode); + + XnUInt32 nPixels = outputMode.nXRes * outputMode.nYRes; + + XnCropping cropping; + GetCropping(cropping); + + if (cropping.bEnabled) + { + nPixels = cropping.nXSize * cropping.nYSize; + } + + m_nBufferSize = nPixels * sizeof(XnIRPixel); +} + +void XN_CALLBACK_TYPE XnSensorIRGenerator::OnResChangedCallback(void* pCookie) +{ + XnSensorIRGenerator* pThis = (XnSensorIRGenerator*)pCookie; + pThis->OnResChanged(); +} + +//--------------------------------------------------------------------------- +// XnExportedSensorIRGenerator class +//--------------------------------------------------------------------------- +XnExportedSensorIRGenerator::XnExportedSensorIRGenerator() : + XnExportedSensorGenerator(XN_NODE_TYPE_IR, XN_STREAM_TYPE_IR) +{} + +XnSensorGenerator* XnExportedSensorIRGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) +{ + return XN_NEW(XnSensorIRGenerator, context, sensor, pSensor, strStreamName); +} diff --git a/Source/XnDeviceSensorV2/XnSensorIRGenerator.h b/Source/XnDeviceSensorV2/XnSensorIRGenerator.h index b3510eb..dc3c827 100644 --- a/Source/XnDeviceSensorV2/XnSensorIRGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorIRGenerator.h @@ -1,71 +1,71 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_IR_GENERATOR_H__ -#define __XN_SENSOR_IR_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorMapGenerator.h" -#include "XnExportedSensorGenerator.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorIRGenerator: - public XnSensorMapGenerator, - virtual public xn::ModuleIRGenerator -{ -public: - XnSensorIRGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - - virtual XnStatus Init(); - - virtual XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - virtual XnUInt32 GetDataSize(); - - virtual XnIRPixel* GetIRMap(); - -private: - void OnResChanged(); - - static void XN_CALLBACK_TYPE OnResChangedCallback(void* pCookie); - - XnCallbackHandle m_hMapModeCallback; - XnCallbackHandle m_hCroppingCallback; - XnUInt32 m_nBufferSize; -}; - -class XnExportedSensorIRGenerator : public XnExportedSensorGenerator -{ -public: - XnExportedSensorIRGenerator(); - virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_IR_GENERATOR_H__ +#define __XN_SENSOR_IR_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorMapGenerator.h" +#include "XnExportedSensorGenerator.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorIRGenerator: + public XnSensorMapGenerator, + virtual public xn::ModuleIRGenerator +{ +public: + XnSensorIRGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + + virtual XnStatus Init(); + + virtual XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + virtual XnUInt32 GetDataSize(); + + virtual XnIRPixel* GetIRMap(); + +private: + void OnResChanged(); + + static void XN_CALLBACK_TYPE OnResChangedCallback(void* pCookie); + + XnCallbackHandle m_hMapModeCallback; + XnCallbackHandle m_hCroppingCallback; + XnUInt32 m_nBufferSize; +}; + +class XnExportedSensorIRGenerator : public XnExportedSensorGenerator +{ +public: + XnExportedSensorIRGenerator(); + virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); +}; + #endif // __XN_SENSOR_IR_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorIRStream.cpp b/Source/XnDeviceSensorV2/XnSensorIRStream.cpp index 30ad6ec..a4c3ea7 100644 --- a/Source/XnDeviceSensorV2/XnSensorIRStream.cpp +++ b/Source/XnDeviceSensorV2/XnSensorIRStream.cpp @@ -1,461 +1,461 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorInit.h" -#include "XnSensorIRStream.h" -#include "XnIRProcessor.h" -#include -#include "XnCmosInfo.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_IR_STREAM_DEFAULT_FPS 30 -#define XN_IR_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA -#define XN_IR_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_RGB24 -#define XN_IR_STREAM_DEFAULT_MIRROR FALSE - -#define XN_IR_MAX_BUFFER_SIZE (XN_SXGA_X_RES * XN_SXGA_Y_RES * sizeof(XnRGB24Pixel)) - -//--------------------------------------------------------------------------- -// XnSensorIRStream class -//--------------------------------------------------------------------------- -XnSensorIRStream::XnSensorIRStream(const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : - XnIRStream(StreamName, FALSE), - m_Helper(pObjects), - m_BufferPool(nBufferCount, StreamName, XN_IR_MAX_BUFFER_SIZE), - m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), - m_FirmwareCropSizeX("FirmwareCropSizeX", 0, StreamName), - m_FirmwareCropSizeY("FirmwareCropSizeY", 0, StreamName), - m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, StreamName), - m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, StreamName), - m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, StreamName), - m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE) -{ - m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); -} - -XnStatus XnSensorIRStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = SetBufferPool(&m_BufferPool); - XN_IS_STATUS_OK(nRetVal); - - // init base - nRetVal = XnIRStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - // add properties - XN_VALIDATE_ADD_PROPERTIES(this, &m_SharedBufferName, &m_ActualRead); - - // set base properties default values - nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_RESOLUTION); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FPSProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_FPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_OUTPUT_FORMAT); - XN_IS_STATUS_OK(nRetVal); - - // init helper - nRetVal = m_Helper.Init(this, this); - XN_IS_STATUS_OK(nRetVal); - - // data processor - nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - // register for mirror - XnCallbackHandle hCallbackDummy; - nRetVal = IsMirroredProperty().OnChangeEvent().Register(IsMirroredChangedCallback, this, &hCallbackDummy); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::Free() -{ - m_Helper.Free(); - XnIRStream::Free(); - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::MapPropertiesToFirmware() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_IRResolution, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_IRFPS, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_IRCropSizeX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_IRCropSizeY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_IRCropOffsetX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_IRCropOffsetY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_IRCropEnabled, TRUE)); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::ConfigureStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); - - nRetVal = SetActualRead(TRUE); - XN_IS_STATUS_OK(nRetVal); - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); - - // IR mirror is always off in firmware - nRetVal = GetFirmwareParams()->m_IRMirror.SetValue(FALSE); - XN_IS_STATUS_OK(nRetVal); - - // CMOS - if (GetResolution() != XN_RESOLUTION_SXGA) - { - nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_DEPTH, GetResolution(), GetFPS()); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::SetActualRead(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_ActualRead.GetValue() != bRead) - { - if (bRead) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB IR read thread..."); - nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificImageUsb->nChunkReadBytes, XN_SENSOR_USB_IMAGE_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificImageUsb); - XN_IS_STATUS_OK(nRetVal); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down IR image read thread..."); - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); - } - - nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::OpenStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_IR); - XN_IS_STATUS_OK(nRetVal); - - // Cropping - if (m_FirmwareCropEnabled.GetValue() == TRUE) - { - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); - } - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); - - - nRetVal = XnIRStream::Open(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensorIRStream::CloseStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIRStream::Close(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetActualRead(FALSE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::SetOutputFormat(XnOutputFormats nOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_RGB24: - case XN_OUTPUT_FORMAT_GRAYSCALE16: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported IR output format: %d", nOutputFormat); - } - - nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIRStream::SetOutputFormat(nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::SetFPS(XnUInt32 nFPS) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIRStream::SetFPS(nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::SetResolution(XnResolutions nResolution) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nResolution) - { - case XN_RESOLUTION_QVGA: - case XN_RESOLUTION_VGA: - break; - case XN_RESOLUTION_SXGA: - if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_5_1) - { - XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "IR resolution is not supported by this firmware!"); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported IR resolution: %d", nResolution); - } - - nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnIRStream::SetResolution(nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::SetCropping(const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ValidateCropping(pCropping); - XN_IS_STATUS_OK(nRetVal); - - xnOSEnterCriticalSection(GetLock()); - - if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) - { - nRetVal = m_Helper.StartFirmwareTransaction(); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - // mirror is done by software (meaning AFTER cropping, which is bad). So we need to flip the cropping area - // to match requested area. - XnUInt16 nXOffset = pCropping->nXOffset; - if (IsMirrored()) - { - nXOffset = GetXRes() - pCropping->nXOffset - pCropping->nXSize; - } - - if (pCropping->bEnabled) - { - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, nXOffset); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); - } - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); - - if (nRetVal != XN_STATUS_OK) - { - m_Helper.RollbackFirmwareTransaction(); - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - } - - nRetVal = XnIRStream::SetCropping(pCropping); - - - xnOSLeaveCriticalSection(GetLock()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const -{ - // in IR, in all resolutions except SXGA, we get additional 8 lines - XnUInt32 nYRes = GetYRes(); - if (GetResolution() != XN_RESOLUTION_SXGA) - { - nYRes += 8; - } - - *pnRequiredSize = GetXRes() * nYRes * GetBytesPerPixel(); - return XN_STATUS_OK; -} - -XnStatus XnSensorIRStream::ReallocTripleFrameBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (IsOpen()) - { - // before actually replacing buffer, lock the processor (so it will not continue to - // use old buffer) - nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = XnIRStream::ReallocTripleFrameBuffer(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - return (nRetVal); - } - - if (IsOpen()) - { - nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // if firmware cropping is disabled, crop - if (m_FirmwareCropEnabled.GetValue() == FALSE) - { - nRetVal = XnIRStream::CropImpl(pStreamOutput, pCropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::CreateDataProcessor(XnDataProcessor** ppProcessor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDataProcessor* pNew; - XN_VALIDATE_NEW_AND_INIT(pNew, XnIRProcessor, this, &m_Helper); - - *ppProcessor = pNew; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::OnIsMirroredChanged() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // if cropping is on, we need to flip it - XnCropping cropping = *GetCropping(); - if (cropping.bEnabled) - { - nRetVal = SetCropping(&cropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorIRStream::IsMirroredChangedCallback(const XnProperty* pSender, void* pCookie) -{ - XnSensorIRStream* pThis = (XnSensorIRStream*)pCookie; - return pThis->OnIsMirroredChanged(); -} - -XnStatus XN_CALLBACK_TYPE XnSensorIRStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorIRStream* pThis = (XnSensorIRStream*)pCookie; - return pThis->SetActualRead(nValue == TRUE); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorInit.h" +#include "XnSensorIRStream.h" +#include "XnIRProcessor.h" +#include +#include "XnCmosInfo.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_IR_STREAM_DEFAULT_FPS 30 +#define XN_IR_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA +#define XN_IR_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_RGB24 +#define XN_IR_STREAM_DEFAULT_MIRROR FALSE + +#define XN_IR_MAX_BUFFER_SIZE (XN_SXGA_X_RES * XN_SXGA_Y_RES * sizeof(XnRGB24Pixel)) + +//--------------------------------------------------------------------------- +// XnSensorIRStream class +//--------------------------------------------------------------------------- +XnSensorIRStream::XnSensorIRStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : + XnIRStream(StreamName, FALSE), + m_Helper(pObjects), + m_BufferPool(nBufferCount, strDeviceName, StreamName, XN_IR_MAX_BUFFER_SIZE), + m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), + m_FirmwareCropSizeX("FirmwareCropSizeX", 0, StreamName), + m_FirmwareCropSizeY("FirmwareCropSizeY", 0, StreamName), + m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, StreamName), + m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, StreamName), + m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, StreamName), + m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE) +{ + m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); +} + +XnStatus XnSensorIRStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = SetBufferPool(&m_BufferPool); + XN_IS_STATUS_OK(nRetVal); + + // init base + nRetVal = XnIRStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + // add properties + XN_VALIDATE_ADD_PROPERTIES(this, &m_SharedBufferName, &m_ActualRead); + + // set base properties default values + nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_RESOLUTION); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FPSProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_FPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_IR_STREAM_DEFAULT_OUTPUT_FORMAT); + XN_IS_STATUS_OK(nRetVal); + + // init helper + nRetVal = m_Helper.Init(this, this); + XN_IS_STATUS_OK(nRetVal); + + // data processor + nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + // register for mirror + XnCallbackHandle hCallbackDummy; + nRetVal = IsMirroredProperty().OnChangeEvent().Register(IsMirroredChangedCallback, this, &hCallbackDummy); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::Free() +{ + m_Helper.Free(); + XnIRStream::Free(); + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::MapPropertiesToFirmware() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_IRResolution, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_IRFPS, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_IRCropSizeX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_IRCropSizeY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_IRCropOffsetX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_IRCropOffsetY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_IRCropEnabled, TRUE)); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::ConfigureStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); + + nRetVal = SetActualRead(TRUE); + XN_IS_STATUS_OK(nRetVal); + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); + + // IR mirror is always off in firmware + nRetVal = GetFirmwareParams()->m_IRMirror.SetValue(FALSE); + XN_IS_STATUS_OK(nRetVal); + + // CMOS + if (GetResolution() != XN_RESOLUTION_SXGA) + { + nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_DEPTH, GetResolution(), GetFPS()); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::SetActualRead(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_ActualRead.GetValue() != bRead) + { + if (bRead) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB IR read thread..."); + nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificImageUsb->nChunkReadBytes, XN_SENSOR_USB_IMAGE_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificImageUsb); + XN_IS_STATUS_OK(nRetVal); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down IR image read thread..."); + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); + } + + nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::OpenStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_IR); + XN_IS_STATUS_OK(nRetVal); + + // Cropping + if (m_FirmwareCropEnabled.GetValue() == TRUE) + { + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); + } + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); + + + nRetVal = XnIRStream::Open(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + + +XnStatus XnSensorIRStream::CloseStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIRStream::Close(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetActualRead(FALSE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::SetOutputFormat(XnOutputFormats nOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_RGB24: + case XN_OUTPUT_FORMAT_GRAYSCALE16: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported IR output format: %d", nOutputFormat); + } + + nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIRStream::SetOutputFormat(nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::SetFPS(XnUInt32 nFPS) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIRStream::SetFPS(nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::SetResolution(XnResolutions nResolution) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nResolution) + { + case XN_RESOLUTION_QVGA: + case XN_RESOLUTION_VGA: + break; + case XN_RESOLUTION_SXGA: + if (m_Helper.GetFirmwareVersion() < XN_SENSOR_FW_VER_5_1) + { + XN_LOG_WARNING_RETURN(XN_STATUS_IO_INVALID_STREAM_IMAGE_RESOLUTION, XN_MASK_DEVICE_SENSOR, "IR resolution is not supported by this firmware!"); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported IR resolution: %d", nResolution); + } + + nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnIRStream::SetResolution(nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::SetCropping(const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ValidateCropping(pCropping); + XN_IS_STATUS_OK(nRetVal); + + xnOSEnterCriticalSection(GetLock()); + + if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) + { + nRetVal = m_Helper.StartFirmwareTransaction(); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + // mirror is done by software (meaning AFTER cropping, which is bad). So we need to flip the cropping area + // to match requested area. + XnUInt16 nXOffset = pCropping->nXOffset; + if (IsMirrored()) + { + nXOffset = GetXRes() - pCropping->nXOffset - pCropping->nXSize; + } + + if (pCropping->bEnabled) + { + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, nXOffset); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); + } + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); + + if (nRetVal != XN_STATUS_OK) + { + m_Helper.RollbackFirmwareTransaction(); + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + } + + nRetVal = XnIRStream::SetCropping(pCropping); + + + xnOSLeaveCriticalSection(GetLock()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::CalcRequiredSize(XnUInt32* pnRequiredSize) const +{ + // in IR, in all resolutions except SXGA, we get additional 8 lines + XnUInt32 nYRes = GetYRes(); + if (GetResolution() != XN_RESOLUTION_SXGA) + { + nYRes += 8; + } + + *pnRequiredSize = GetXRes() * nYRes * GetBytesPerPixel(); + return XN_STATUS_OK; +} + +XnStatus XnSensorIRStream::ReallocTripleFrameBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (IsOpen()) + { + // before actually replacing buffer, lock the processor (so it will not continue to + // use old buffer) + nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = XnIRStream::ReallocTripleFrameBuffer(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + return (nRetVal); + } + + if (IsOpen()) + { + nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // if firmware cropping is disabled, crop + if (m_FirmwareCropEnabled.GetValue() == FALSE) + { + nRetVal = XnIRStream::CropImpl(pStreamOutput, pCropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::CreateDataProcessor(XnDataProcessor** ppProcessor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnDataProcessor* pNew; + XN_VALIDATE_NEW_AND_INIT(pNew, XnIRProcessor, this, &m_Helper); + + *ppProcessor = pNew; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::OnIsMirroredChanged() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // if cropping is on, we need to flip it + XnCropping cropping = *GetCropping(); + if (cropping.bEnabled) + { + nRetVal = SetCropping(&cropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorIRStream::IsMirroredChangedCallback(const XnProperty* pSender, void* pCookie) +{ + XnSensorIRStream* pThis = (XnSensorIRStream*)pCookie; + return pThis->OnIsMirroredChanged(); +} + +XnStatus XN_CALLBACK_TYPE XnSensorIRStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorIRStream* pThis = (XnSensorIRStream*)pCookie; + return pThis->SetActualRead(nValue == TRUE); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorIRStream.h b/Source/XnDeviceSensorV2/XnSensorIRStream.h index 68ab322..4f74d5b 100644 --- a/Source/XnDeviceSensorV2/XnSensorIRStream.h +++ b/Source/XnDeviceSensorV2/XnSensorIRStream.h @@ -1,107 +1,107 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_IR_STREAM_H__ -#define __XN_SENSOR_IR_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensorStreamHelper.h" -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// XnSensorIRStream class -//--------------------------------------------------------------------------- -class XnSensorIRStream : public XnIRStream, public IXnSensorStream -{ -public: - XnSensorIRStream(const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); - ~XnSensorIRStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } - - inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } - - friend class XnIRProcessor; - -protected: - inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Open() { return m_Helper.Open(); } - XnStatus Close() { return m_Helper.Close(); } - XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; - XnStatus ReallocTripleFrameBuffer(); - XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); - XnStatus ConfigureStreamImpl(); - XnStatus OpenStreamImpl(); - XnStatus CloseStreamImpl(); - XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); - XnStatus MapPropertiesToFirmware(); - void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } - XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } - XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); - XnStatus SetResolution(XnResolutions nResolution); - XnStatus SetFPS(XnUInt32 nFPS); - XnStatus SetCropping(const XnCropping* pCropping); - XnStatus SetActualRead(XnBool bRead); - -private: - XnStatus OnIsMirroredChanged(); - - - static XnStatus XN_CALLBACK_TYPE IsMirroredChangedCallback(const XnProperty* pSender, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - XnSensorStreamHelper m_Helper; - XnSharedMemoryBufferPool m_BufferPool; - - XnActualStringProperty m_SharedBufferName; - XnActualIntProperty m_FirmwareCropSizeX; - XnActualIntProperty m_FirmwareCropSizeY; - XnActualIntProperty m_FirmwareCropOffsetX; - XnActualIntProperty m_FirmwareCropOffsetY; - XnActualIntProperty m_FirmwareCropEnabled; - - XnActualIntProperty m_ActualRead; -}; - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_IR_STREAM_H__ +#define __XN_SENSOR_IR_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensorStreamHelper.h" +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// XnSensorIRStream class +//--------------------------------------------------------------------------- +class XnSensorIRStream : public XnIRStream, public IXnSensorStream +{ +public: + XnSensorIRStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); + ~XnSensorIRStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } + + inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } + + friend class XnIRProcessor; + +protected: + inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Open() { return m_Helper.Open(); } + XnStatus Close() { return m_Helper.Close(); } + XnStatus CalcRequiredSize(XnUInt32* pnRequiredSize) const; + XnStatus ReallocTripleFrameBuffer(); + XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); + XnStatus ConfigureStreamImpl(); + XnStatus OpenStreamImpl(); + XnStatus CloseStreamImpl(); + XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); + XnStatus MapPropertiesToFirmware(); + void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } + XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } + XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); + XnStatus SetResolution(XnResolutions nResolution); + XnStatus SetFPS(XnUInt32 nFPS); + XnStatus SetCropping(const XnCropping* pCropping); + XnStatus SetActualRead(XnBool bRead); + +private: + XnStatus OnIsMirroredChanged(); + + + static XnStatus XN_CALLBACK_TYPE IsMirroredChangedCallback(const XnProperty* pSender, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + XnSensorStreamHelper m_Helper; + XnSharedMemoryBufferPool m_BufferPool; + + XnActualStringProperty m_SharedBufferName; + XnActualIntProperty m_FirmwareCropSizeX; + XnActualIntProperty m_FirmwareCropSizeY; + XnActualIntProperty m_FirmwareCropOffsetX; + XnActualIntProperty m_FirmwareCropOffsetY; + XnActualIntProperty m_FirmwareCropEnabled; + + XnActualIntProperty m_ActualRead; +}; + + #endif //__XN_SENSOR_IR_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorImageGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorImageGenerator.cpp index 1516020..f452b22 100644 --- a/Source/XnDeviceSensorV2/XnSensorImageGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorImageGenerator.cpp @@ -1,176 +1,176 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorImageGenerator.h" -#include - -//--------------------------------------------------------------------------- -// XnSensorImageGenerator class -//--------------------------------------------------------------------------- -XnSensorImageGenerator::XnSensorImageGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorMapGenerator(context, sensor, pSensor, strStreamName) -{} - -XnStatus XnSensorImageGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorMapGenerator::Init(); - XN_IS_STATUS_OK(nRetVal); - - // add supported modes unique for image - XnMapOutputMode mode; - - switch (m_Version.FWVer) - { - case XN_SENSOR_FW_VER_5_1: - case XN_SENSOR_FW_VER_5_2: - // UXGA 30 - mode.nXRes = XN_UXGA_X_RES; - mode.nYRes = XN_UXGA_Y_RES; - mode.nFPS = 30; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - break; - case XN_SENSOR_FW_VER_5_3: - // SXGA 30 - mode.nXRes = XN_SXGA_X_RES; - mode.nYRes = XN_SXGA_Y_RES; - mode.nFPS = 30; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - break; - } - - return (XN_STATUS_OK); -} - -XnBool XnSensorImageGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName); -} - -XnUInt8* XnSensorImageGenerator::GetImageMap() -{ - return (XnUInt8*)m_pStreamData->pData; -} - -XnBool XnSensorImageGenerator::IsPixelFormatSupported(XnPixelFormat Format) -{ - switch (Format) - { - case XN_PIXEL_FORMAT_RGB24: - case XN_PIXEL_FORMAT_YUV422: - case XN_PIXEL_FORMAT_GRAYSCALE_8_BIT: - return TRUE; - default: - return FALSE; - } -} - -XnStatus XnSensorImageGenerator::SetPixelFormat(XnPixelFormat Format) -{ - if (GetPixelFormat() == Format) - { - return (XN_STATUS_OK); - } - - XnOutputFormats OutputFormat; - - switch (Format) - { - case XN_PIXEL_FORMAT_RGB24: - OutputFormat = XN_OUTPUT_FORMAT_RGB24; - break; - case XN_PIXEL_FORMAT_YUV422: - OutputFormat = XN_OUTPUT_FORMAT_YUV422; - break; - case XN_PIXEL_FORMAT_GRAYSCALE_8_BIT: - OutputFormat = XN_OUTPUT_FORMAT_GRAYSCALE8; - break; - default: - return XN_STATUS_INVALID_OPERATION; - } - - return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)OutputFormat); -} - -XnPixelFormat XnSensorImageGenerator::GetPixelFormat() -{ - XnUInt64 nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_OUTPUT_FORMAT, &nValue); - - switch (nValue) - { - case XN_OUTPUT_FORMAT_RGB24: - return XN_PIXEL_FORMAT_RGB24; - case XN_OUTPUT_FORMAT_YUV422: - return XN_PIXEL_FORMAT_YUV422; - case XN_OUTPUT_FORMAT_GRAYSCALE8: - return XN_PIXEL_FORMAT_GRAYSCALE_8_BIT; - default: - xnLogError(XN_MASK_DEVICE_SENSOR, "Unknown output format: %d", nValue); - return (XnPixelFormat)-1; - } -} - -XnStatus XnSensorImageGenerator::RegisterToPixelFormatChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_OUTPUT_FORMAT, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorImageGenerator::UnregisterFromPixelFormatChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorImageGenerator::FilterProperties(XnActualPropertiesHash* pHash) -{ - XnSensorMapGenerator::FilterProperties(pHash); - pHash->Remove(XN_STREAM_PROPERTY_OUTPUT_FORMAT); -} - -//--------------------------------------------------------------------------- -// XnExportedSensorImageGenerator class -//--------------------------------------------------------------------------- -XnExportedSensorImageGenerator::XnExportedSensorImageGenerator() : - XnExportedSensorGenerator(XN_NODE_TYPE_IMAGE, XN_STREAM_TYPE_IMAGE) -{} - -XnSensorGenerator* XnExportedSensorImageGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) -{ - return XN_NEW(XnSensorImageGenerator, context, sensor, pSensor, strStreamName); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorImageGenerator.h" +#include + +//--------------------------------------------------------------------------- +// XnSensorImageGenerator class +//--------------------------------------------------------------------------- +XnSensorImageGenerator::XnSensorImageGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorMapGenerator(context, sensor, pSensor, strStreamName) +{} + +XnStatus XnSensorImageGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorMapGenerator::Init(); + XN_IS_STATUS_OK(nRetVal); + + // add supported modes unique for image + XnMapOutputMode mode; + + switch (m_Version.FWVer) + { + case XN_SENSOR_FW_VER_5_1: + case XN_SENSOR_FW_VER_5_2: + // UXGA 30 + mode.nXRes = XN_UXGA_X_RES; + mode.nYRes = XN_UXGA_Y_RES; + mode.nFPS = 30; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + break; + case XN_SENSOR_FW_VER_5_3: + // SXGA 30 + mode.nXRes = XN_SXGA_X_RES; + mode.nYRes = XN_SXGA_Y_RES; + mode.nFPS = 30; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + break; + } + + return (XN_STATUS_OK); +} + +XnBool XnSensorImageGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return XnSensorMapGenerator::IsCapabilitySupported(strCapabilityName); +} + +XnUInt8* XnSensorImageGenerator::GetImageMap() +{ + return (XnUInt8*)m_pStreamData->pData; +} + +XnBool XnSensorImageGenerator::IsPixelFormatSupported(XnPixelFormat Format) +{ + switch (Format) + { + case XN_PIXEL_FORMAT_RGB24: + case XN_PIXEL_FORMAT_YUV422: + case XN_PIXEL_FORMAT_GRAYSCALE_8_BIT: + return TRUE; + default: + return FALSE; + } +} + +XnStatus XnSensorImageGenerator::SetPixelFormat(XnPixelFormat Format) +{ + if (GetPixelFormat() == Format) + { + return (XN_STATUS_OK); + } + + XnOutputFormats OutputFormat; + + switch (Format) + { + case XN_PIXEL_FORMAT_RGB24: + OutputFormat = XN_OUTPUT_FORMAT_RGB24; + break; + case XN_PIXEL_FORMAT_YUV422: + OutputFormat = XN_OUTPUT_FORMAT_YUV422; + break; + case XN_PIXEL_FORMAT_GRAYSCALE_8_BIT: + OutputFormat = XN_OUTPUT_FORMAT_GRAYSCALE8; + break; + default: + return XN_STATUS_INVALID_OPERATION; + } + + return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_OUTPUT_FORMAT, (XnUInt64)OutputFormat); +} + +XnPixelFormat XnSensorImageGenerator::GetPixelFormat() +{ + XnUInt64 nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_OUTPUT_FORMAT, &nValue); + + switch (nValue) + { + case XN_OUTPUT_FORMAT_RGB24: + return XN_PIXEL_FORMAT_RGB24; + case XN_OUTPUT_FORMAT_YUV422: + return XN_PIXEL_FORMAT_YUV422; + case XN_OUTPUT_FORMAT_GRAYSCALE8: + return XN_PIXEL_FORMAT_GRAYSCALE_8_BIT; + default: + xnLogError(XN_MASK_DEVICE_SENSOR, "Unknown output format: %d", nValue); + return (XnPixelFormat)-1; + } +} + +XnStatus XnSensorImageGenerator::RegisterToPixelFormatChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_OUTPUT_FORMAT, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorImageGenerator::UnregisterFromPixelFormatChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorImageGenerator::FilterProperties(XnActualPropertiesHash* pHash) +{ + XnSensorMapGenerator::FilterProperties(pHash); + pHash->Remove(XN_STREAM_PROPERTY_OUTPUT_FORMAT); +} + +//--------------------------------------------------------------------------- +// XnExportedSensorImageGenerator class +//--------------------------------------------------------------------------- +XnExportedSensorImageGenerator::XnExportedSensorImageGenerator() : + XnExportedSensorGenerator(XN_NODE_TYPE_IMAGE, XN_STREAM_TYPE_IMAGE) +{} + +XnSensorGenerator* XnExportedSensorImageGenerator::CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) +{ + return XN_NEW(XnSensorImageGenerator, context, sensor, pSensor, strStreamName); +} diff --git a/Source/XnDeviceSensorV2/XnSensorImageGenerator.h b/Source/XnDeviceSensorV2/XnSensorImageGenerator.h index 82983cd..2dc8d15 100644 --- a/Source/XnDeviceSensorV2/XnSensorImageGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorImageGenerator.h @@ -1,69 +1,69 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_IMAGE_GENERATOR_H__ -#define __XN_SENSOR_IMAGE_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorMapGenerator.h" -#include "XnExportedSensorGenerator.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorImageGenerator: - public XnSensorMapGenerator, - virtual public xn::ModuleImageGenerator -{ -public: - XnSensorImageGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - - XnStatus Init(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - XnUInt8* GetImageMap(); - XnBool IsPixelFormatSupported(XnPixelFormat Format); - XnStatus SetPixelFormat(XnPixelFormat Format); - XnPixelFormat GetPixelFormat(); - XnStatus RegisterToPixelFormatChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromPixelFormatChange(XnCallbackHandle hCallback); - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); -}; - -class XnExportedSensorImageGenerator : public XnExportedSensorGenerator -{ -public: - XnExportedSensorImageGenerator(); - virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_IMAGE_GENERATOR_H__ +#define __XN_SENSOR_IMAGE_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorMapGenerator.h" +#include "XnExportedSensorGenerator.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorImageGenerator: + public XnSensorMapGenerator, + virtual public xn::ModuleImageGenerator +{ +public: + XnSensorImageGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + + XnStatus Init(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + XnUInt8* GetImageMap(); + XnBool IsPixelFormatSupported(XnPixelFormat Format); + XnStatus SetPixelFormat(XnPixelFormat Format); + XnPixelFormat GetPixelFormat(); + XnStatus RegisterToPixelFormatChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromPixelFormatChange(XnCallbackHandle hCallback); + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); +}; + +class XnExportedSensorImageGenerator : public XnExportedSensorGenerator +{ +public: + XnExportedSensorImageGenerator(); + virtual XnSensorGenerator* CreateGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); +}; + #endif // __XN_SENSOR_IMAGE_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorImageStream.cpp b/Source/XnDeviceSensorV2/XnSensorImageStream.cpp index 7f39b8b..8796dcd 100644 --- a/Source/XnDeviceSensorV2/XnSensorImageStream.cpp +++ b/Source/XnDeviceSensorV2/XnSensorImageStream.cpp @@ -1,670 +1,670 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensorInit.h" -#include "XnSensorImageStream.h" -#include "XnSensor.h" -#include "XnBayerImageProcessor.h" -#include "XnUncompressedBayerProcessor.h" -#include "XnPSCompressedImageProcessor.h" -#include "XnJpegImageProcessor.h" -#include "XnUncompressedYUVImageProcessor.h" -#include "XnUncompressedYUVtoRGBImageProcessor.h" -#include "YUV.h" -#include "Bayer.h" -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_IMAGE_STREAM_DEFAULT_FPS 30 -#define XN_IMAGE_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA -#define XN_IMAGE_STREAM_DEFAULT_INPUT_FORMAT XN_IO_IMAGE_FORMAT_YUV422 -#define XN_IMAGE_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_RGB24 -#define XN_IMAGE_STREAM_DEFAULT_FLICKER 0 -#define XN_IMAGE_STREAM_DEFAULT_QUALITY 10 - -//--------------------------------------------------------------------------- -// XnSensorImageStream class -//--------------------------------------------------------------------------- -XnSensorImageStream::XnSensorImageStream(const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : - XnImageStream(StreamName, FALSE), - m_Helper(pObjects), - m_BufferPool(nBufferCount, StreamName, GetMaxBufferSize(m_Helper.GetFirmwareVersion())), - m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), - m_InputFormat(XN_STREAM_PROPERTY_INPUT_FORMAT, XN_IMAGE_STREAM_DEFAULT_INPUT_FORMAT), - m_AntiFlicker(XN_STREAM_PROPERTY_FLICKER, XN_IMAGE_STREAM_DEFAULT_FLICKER), - m_ImageQuality(XN_STREAM_PROPERTY_QUALITY, XN_IMAGE_STREAM_DEFAULT_QUALITY), - m_FirmwareMirror("FirmwareMirror", FALSE, StreamName), - m_FirmwareCropSizeX("FirmwareCropSizeX", 0, StreamName), - m_FirmwareCropSizeY("FirmwareCropSizeY", 0, StreamName), - m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, StreamName), - m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, StreamName), - m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, StreamName), - m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE) -{ - m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); -} - -XnStatus XnSensorImageStream::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = SetBufferPool(&m_BufferPool); - XN_IS_STATUS_OK(nRetVal); - - // init base - nRetVal = XnImageStream::Init(); - XN_IS_STATUS_OK(nRetVal); - - m_InputFormat.UpdateSetCallback(SetInputFormatCallback, this); - m_AntiFlicker.UpdateSetCallback(SetAntiFlickerCallback, this); - m_ImageQuality.UpdateSetCallback(SetImageQualityCallback, this); - - // add properties - XN_VALIDATE_ADD_PROPERTIES(this, &m_InputFormat, &m_AntiFlicker, &m_ImageQuality, - &m_SharedBufferName, &m_ActualRead); - - // set base properties default values - nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_RESOLUTION); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = FPSProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_FPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_OUTPUT_FORMAT); - XN_IS_STATUS_OK(nRetVal); - - // init helper - nRetVal = m_Helper.Init(this, this); - XN_IS_STATUS_OK(nRetVal); - - // data processor - nRetVal = m_Helper.RegisterDataProcessorProperty(m_InputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::Free() -{ - m_Helper.Free(); - XnImageStream::Free(); - return (XN_STATUS_OK); -} - -XnUInt32 XnSensorImageStream::GetMaxBufferSize(XnFWVer version) -{ - if (version >= XN_SENSOR_FW_VER_5_3) - { - // max resolution is only SXGA - return (XN_SXGA_X_RES * XN_SXGA_Y_RES * sizeof(XnRGB24Pixel)); - } - else - { - // max resolution is UXGA - return (XN_UXGA_X_RES * XN_UXGA_Y_RES * sizeof(XnRGB24Pixel)); - } -} - -XnStatus XnSensorImageStream::MapPropertiesToFirmware() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_InputFormat, GetFirmwareParams()->m_ImageFormat, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_ImageResolution, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_ImageFPS, FALSE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_AntiFlicker, GetFirmwareParams()->m_ImageFlickerDetection, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_ImageQuality, GetFirmwareParams()->m_ImageQuality, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareMirror, GetFirmwareParams()->m_ImageMirror, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_ImageCropSizeX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_ImageCropSizeY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_ImageCropOffsetX, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_ImageCropOffsetY, TRUE)); - XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_ImageCropEnabled, TRUE)); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::ValidateMode() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // validity checks - XnIOImageFormats nInputFormat = (XnIOImageFormats)m_InputFormat.GetValue(); - XnOutputFormats nOutputFormat = GetOutputFormat(); - XnResolutions nResolution = GetResolution(); - - // Avin: Removed to enable 1280x1024 Image - // check resolution - /* - if ((nResolution == XN_RESOLUTION_UXGA || nResolution == XN_RESOLUTION_SXGA) && nInputFormat != XN_IO_IMAGE_FORMAT_BAYER) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "UXGA resolution is only supported with BAYER input!"); - } - */ - - // check output format - if (nOutputFormat == XN_OUTPUT_FORMAT_GRAYSCALE8 && nInputFormat != XN_IO_IMAGE_FORMAT_BAYER) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Grayscale8 output requires BAYER input!"); - } - else if (nOutputFormat == XN_OUTPUT_FORMAT_YUV422 && nInputFormat != XN_IO_IMAGE_FORMAT_YUV422 && nInputFormat != XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "YUV output requires YUV input!"); - } - - // check input format - if (nInputFormat == XN_IO_IMAGE_FORMAT_BAYER && nResolution != XN_RESOLUTION_UXGA && nResolution != XN_RESOLUTION_SXGA) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "BAYER input requires SXGA/UXGA resolution!"); - } - else if (nInputFormat == XN_IO_IMAGE_FORMAT_JPEG && nOutputFormat != XN_OUTPUT_FORMAT_RGB24) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Jpeg input is only supported for RGB24 output!"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::ConfigureStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); - - nRetVal = SetActualRead(TRUE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = ValidateMode(); - XN_IS_STATUS_OK(nRetVal); - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_InputFormat)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_AntiFlicker)); - - // image quality is only relevant for JPEG - if (m_InputFormat.GetValue() == XN_IO_IMAGE_FORMAT_JPEG) - { - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_ImageQuality)); - } - - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareMirror)); - - if (GetResolution() != XN_RESOLUTION_UXGA && GetResolution() != XN_RESOLUTION_SXGA) - { - nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_IMAGE, GetResolution(), GetFPS()); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetActualRead(XnBool bRead) -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_ActualRead.GetValue() != bRead) - { - if (bRead) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB image read thread..."); - nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificImageUsb->nChunkReadBytes, XN_SENSOR_USB_IMAGE_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificImageUsb); - XN_IS_STATUS_OK(nRetVal); - } - else - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB image read thread..."); - xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); - } - - nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::OpenStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_COLOR); - XN_IS_STATUS_OK(nRetVal); - - // Cropping - if (m_FirmwareCropEnabled.GetValue() == TRUE) - { - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); - } - XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); - - nRetVal = XnImageStream::Open(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::CloseStreamImpl() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnImageStream::Close(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = SetActualRead(FALSE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetOutputFormat(XnOutputFormats nOutputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nOutputFormat) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - case XN_OUTPUT_FORMAT_YUV422: - case XN_OUTPUT_FORMAT_RGB24: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported image output format: %d", nOutputFormat); - } - - nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnImageStream::SetOutputFormat(nOutputFormat); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingDataProcessorProperty(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetMirror(XnBool bIsMirrored) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // set firmware mirror - XnBool bFirmwareMirror = (bIsMirrored == TRUE && m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_0); - - xnOSEnterCriticalSection(GetLock()); - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareMirror, bFirmwareMirror); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - // update prop - nRetVal = XnImageStream::SetMirror(bIsMirrored); - xnOSLeaveCriticalSection(GetLock()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetFPS(XnUInt32 nFPS) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnImageStream::SetFPS(nFPS); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetResolution(XnResolutions nResolution) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (nResolution) - { - case XN_RESOLUTION_QVGA: - case XN_RESOLUTION_VGA: - case XN_RESOLUTION_SXGA: - case XN_RESOLUTION_UXGA: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown resolution: %u", nResolution); - } - - nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnImageStream::SetResolution(nResolution); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetInputFormat(XnIOImageFormats nInputFormat) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // validity checks - switch (nInputFormat) - { - case XN_IO_IMAGE_FORMAT_YUV422: - case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: - case XN_IO_IMAGE_FORMAT_JPEG: - case XN_IO_IMAGE_FORMAT_BAYER: - case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER: - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown image input format: %d", nInputFormat); - } - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_InputFormat, nInputFormat); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetAntiFlicker(XnUInt32 nFrequency) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_Helper.SimpleSetFirmwareParam(m_AntiFlicker, nFrequency); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetImageQuality(XnUInt32 nQuality) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // check relevance - if (m_InputFormat.GetValue() != XN_IO_IMAGE_FORMAT_JPEG) - { - XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER, XN_MASK_DEVICE_SENSOR, "Image quality is only supported when input format is JPEG"); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::SetCropping(const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = ValidateCropping(pCropping); - XN_IS_STATUS_OK(nRetVal); - - xnOSEnterCriticalSection(GetLock()); - - if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) - { - nRetVal = m_Helper.StartFirmwareTransaction(); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - if (pCropping->bEnabled) - { - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, pCropping->nXOffset); - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); - } - - if (nRetVal == XN_STATUS_OK) - nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); - - if (nRetVal != XN_STATUS_OK) - { - m_Helper.RollbackFirmwareTransaction(); - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - - nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); - m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); - m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); - xnOSLeaveCriticalSection(GetLock()); - return (nRetVal); - } - } - - nRetVal = XnImageStream::SetCropping(pCropping); - xnOSLeaveCriticalSection(GetLock()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::PostProcessFrame(XnStreamData* pFrameData) -{ - XnStatus nRetVal = XN_STATUS_OK; - - m_Helper.GetFPS()->MarkOutputImage(pFrameData->nFrameID, pFrameData->nTimestamp); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::ReallocTripleFrameBuffer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (IsOpen()) - { - // before actually replacing buffer, lock the processor (so it will not continue to - // use old buffer) - nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = XnImageStream::ReallocTripleFrameBuffer(); - if (nRetVal != XN_STATUS_OK) - { - m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - return (nRetVal); - } - - if (IsOpen()) - { - nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // if firmware cropping is disabled, crop - if (m_FirmwareCropEnabled.GetValue() == FALSE) - { - nRetVal = XnImageStream::CropImpl(pStreamOutput, pCropping); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorImageStream::Mirror(XnStreamData* pStreamOutput) const -{ - XnStatus nRetVal = XN_STATUS_OK; - - // only perform mirror if it's our job. if mirror is performed by FW, we don't need to do anything. - if (m_FirmwareMirror.GetValue() == FALSE) - { - nRetVal = XnImageStream::Mirror(pStreamOutput); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnUInt32 XnSensorImageStream::CalculateExpectedSize() -{ - XnUInt32 nExpectedImageBufferSize = GetXRes() * GetYRes(); - - // when cropping is turned on, actual IR size is smaller - const XnCropping* pCropping = GetCropping(); - if (pCropping->bEnabled) - { - nExpectedImageBufferSize = pCropping->nXSize * pCropping->nYSize; - } - - switch (m_InputFormat.GetValue()) - { - case XN_IO_IMAGE_FORMAT_YUV422: - case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: - // in YUV each pixel is represented in 2 bytes (actually 2 pixels are represented by 4 bytes) - nExpectedImageBufferSize *= 2; - break; - case XN_IO_IMAGE_FORMAT_BAYER: - // each pixel is one byte. - break; - case XN_IO_IMAGE_FORMAT_JPEG: - // image should be in RGB now - 3 bytes a pixel - nExpectedImageBufferSize *= 3; - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Does not know to calculate expected size for input format %d", m_InputFormat.GetValue()); - } - - return nExpectedImageBufferSize; -} - -XnStatus XnSensorImageStream::CreateDataProcessor(XnDataProcessor** ppProcessor) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnStreamProcessor* pNew; - - switch (m_InputFormat.GetValue()) - { - case XN_IO_IMAGE_FORMAT_BAYER: - XN_VALIDATE_NEW_AND_INIT(pNew, XnBayerImageProcessor, this, &m_Helper); - break; - case XN_IO_IMAGE_FORMAT_YUV422: - XN_VALIDATE_NEW_AND_INIT(pNew, XnPSCompressedImageProcessor, this, &m_Helper); - break; - case XN_IO_IMAGE_FORMAT_JPEG: - XN_VALIDATE_NEW_AND_INIT(pNew, XnJpegImageProcessor, this, &m_Helper); - break; - case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: - if (GetOutputFormat() == XN_OUTPUT_FORMAT_YUV422) - { - XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedYUVImageProcessor, this, &m_Helper); - } - else if (GetOutputFormat() == XN_OUTPUT_FORMAT_RGB24) - { - XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedYUVtoRGBImageProcessor, this, &m_Helper); - } - else - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "invalid ouput format %d!", GetOutputFormat()); - } - break; - case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER: - XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedBayerProcessor, this, &m_Helper); - break; - default: - return XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT; - } - - *ppProcessor = pNew; - - return XN_STATUS_OK; -} - -XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; - return pThis->SetInputFormat((XnIOImageFormats)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetAntiFlickerCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; - return pThis->SetAntiFlicker((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetImageQualityCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; - return pThis->SetImageQuality((XnUInt32)nValue); -} - -XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; - return pThis->SetActualRead(nValue == TRUE); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensorInit.h" +#include "XnSensorImageStream.h" +#include "XnSensor.h" +#include "XnBayerImageProcessor.h" +#include "XnUncompressedBayerProcessor.h" +#include "XnPSCompressedImageProcessor.h" +#include "XnJpegImageProcessor.h" +#include "XnUncompressedYUVImageProcessor.h" +#include "XnUncompressedYUVtoRGBImageProcessor.h" +#include "YUV.h" +#include "Bayer.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_IMAGE_STREAM_DEFAULT_FPS 30 +#define XN_IMAGE_STREAM_DEFAULT_RESOLUTION XN_RESOLUTION_QVGA +#define XN_IMAGE_STREAM_DEFAULT_INPUT_FORMAT XN_IO_IMAGE_FORMAT_YUV422 +#define XN_IMAGE_STREAM_DEFAULT_OUTPUT_FORMAT XN_OUTPUT_FORMAT_RGB24 +#define XN_IMAGE_STREAM_DEFAULT_FLICKER 0 +#define XN_IMAGE_STREAM_DEFAULT_QUALITY 10 + +//--------------------------------------------------------------------------- +// XnSensorImageStream class +//--------------------------------------------------------------------------- +XnSensorImageStream::XnSensorImageStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount) : + XnImageStream(StreamName, FALSE), + m_Helper(pObjects), + m_BufferPool(nBufferCount, strDeviceName, StreamName, GetMaxBufferSize(m_Helper.GetFirmwareVersion())), + m_SharedBufferName(XN_STREAM_PROPERTY_SHARED_BUFFER_NAME, m_BufferPool.GetSharedMemoryName()), + m_InputFormat(XN_STREAM_PROPERTY_INPUT_FORMAT, XN_IMAGE_STREAM_DEFAULT_INPUT_FORMAT), + m_AntiFlicker(XN_STREAM_PROPERTY_FLICKER, XN_IMAGE_STREAM_DEFAULT_FLICKER), + m_ImageQuality(XN_STREAM_PROPERTY_QUALITY, XN_IMAGE_STREAM_DEFAULT_QUALITY), + m_FirmwareMirror("FirmwareMirror", FALSE, StreamName), + m_FirmwareCropSizeX("FirmwareCropSizeX", 0, StreamName), + m_FirmwareCropSizeY("FirmwareCropSizeY", 0, StreamName), + m_FirmwareCropOffsetX("FirmwareCropOffsetX", 0, StreamName), + m_FirmwareCropOffsetY("FirmwareCropOffsetY", 0, StreamName), + m_FirmwareCropEnabled("FirmwareCropEnabled", FALSE, StreamName), + m_ActualRead(XN_STREAM_PROPERTY_ACTUAL_READ_DATA, FALSE) +{ + m_ActualRead.UpdateSetCallback(SetActualReadCallback, this); +} + +XnStatus XnSensorImageStream::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = SetBufferPool(&m_BufferPool); + XN_IS_STATUS_OK(nRetVal); + + // init base + nRetVal = XnImageStream::Init(); + XN_IS_STATUS_OK(nRetVal); + + m_InputFormat.UpdateSetCallback(SetInputFormatCallback, this); + m_AntiFlicker.UpdateSetCallback(SetAntiFlickerCallback, this); + m_ImageQuality.UpdateSetCallback(SetImageQualityCallback, this); + + // add properties + XN_VALIDATE_ADD_PROPERTIES(this, &m_InputFormat, &m_AntiFlicker, &m_ImageQuality, + &m_SharedBufferName, &m_ActualRead); + + // set base properties default values + nRetVal = ResolutionProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_RESOLUTION); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = FPSProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_FPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = OutputFormatProperty().UnsafeUpdateValue(XN_IMAGE_STREAM_DEFAULT_OUTPUT_FORMAT); + XN_IS_STATUS_OK(nRetVal); + + // init helper + nRetVal = m_Helper.Init(this, this); + XN_IS_STATUS_OK(nRetVal); + + // data processor + nRetVal = m_Helper.RegisterDataProcessorProperty(m_InputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.RegisterDataProcessorProperty(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::Free() +{ + m_Helper.Free(); + XnImageStream::Free(); + return (XN_STATUS_OK); +} + +XnUInt32 XnSensorImageStream::GetMaxBufferSize(XnFWVer version) +{ + if (version >= XN_SENSOR_FW_VER_5_3) + { + // max resolution is only SXGA + return (XN_SXGA_X_RES * XN_SXGA_Y_RES * sizeof(XnRGB24Pixel)); + } + else + { + // max resolution is UXGA + return (XN_UXGA_X_RES * XN_UXGA_Y_RES * sizeof(XnRGB24Pixel)); + } +} + +XnStatus XnSensorImageStream::MapPropertiesToFirmware() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_InputFormat, GetFirmwareParams()->m_ImageFormat, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(ResolutionProperty(), GetFirmwareParams()->m_ImageResolution, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(FPSProperty(), GetFirmwareParams()->m_ImageFPS, FALSE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_AntiFlicker, GetFirmwareParams()->m_ImageFlickerDetection, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_ImageQuality, GetFirmwareParams()->m_ImageQuality, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareMirror, GetFirmwareParams()->m_ImageMirror, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeX, GetFirmwareParams()->m_ImageCropSizeX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropSizeY, GetFirmwareParams()->m_ImageCropSizeY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetX, GetFirmwareParams()->m_ImageCropOffsetX, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropOffsetY, GetFirmwareParams()->m_ImageCropOffsetY, TRUE)); + XN_IS_STATUS_OK(m_Helper.MapFirmwareProperty(m_FirmwareCropEnabled, GetFirmwareParams()->m_ImageCropEnabled, TRUE)); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::ValidateMode() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // validity checks + XnIOImageFormats nInputFormat = (XnIOImageFormats)m_InputFormat.GetValue(); + XnOutputFormats nOutputFormat = GetOutputFormat(); + XnResolutions nResolution = GetResolution(); + + // Avin: Removed to enable 1280x1024 Image + // check resolution + /* + if ((nResolution == XN_RESOLUTION_UXGA || nResolution == XN_RESOLUTION_SXGA) && nInputFormat != XN_IO_IMAGE_FORMAT_BAYER) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "UXGA resolution is only supported with BAYER input!"); + } + */ + + // check output format + if (nOutputFormat == XN_OUTPUT_FORMAT_GRAYSCALE8 && nInputFormat != XN_IO_IMAGE_FORMAT_BAYER) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Grayscale8 output requires BAYER input!"); + } + else if (nOutputFormat == XN_OUTPUT_FORMAT_YUV422 && nInputFormat != XN_IO_IMAGE_FORMAT_YUV422 && nInputFormat != XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "YUV output requires YUV input!"); + } + + // check input format + if (nInputFormat == XN_IO_IMAGE_FORMAT_BAYER && nResolution != XN_RESOLUTION_UXGA && nResolution != XN_RESOLUTION_SXGA) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "BAYER input requires SXGA/UXGA resolution!"); + } + else if (nInputFormat == XN_IO_IMAGE_FORMAT_JPEG && nOutputFormat != XN_OUTPUT_FORMAT_RGB24) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Jpeg input is only supported for RGB24 output!"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::ConfigureStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); + + nRetVal = SetActualRead(TRUE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = ValidateMode(); + XN_IS_STATUS_OK(nRetVal); + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_InputFormat)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(ResolutionProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(FPSProperty())); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_AntiFlicker)); + + // image quality is only relevant for JPEG + if (m_InputFormat.GetValue() == XN_IO_IMAGE_FORMAT_JPEG) + { + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_ImageQuality)); + } + + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareMirror)); + + if (GetResolution() != XN_RESOLUTION_UXGA && GetResolution() != XN_RESOLUTION_SXGA) + { + nRetVal = m_Helper.GetCmosInfo()->SetCmosConfig(XN_CMOS_TYPE_IMAGE, GetResolution(), GetFPS()); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetActualRead(XnBool bRead) +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_ActualRead.GetValue() != bRead) + { + if (bRead) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Creating USB image read thread..."); + nRetVal = xnUSBInitReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp, GetHelper()->GetPrivateData()->pSpecificImageUsb->nChunkReadBytes, XN_SENSOR_USB_IMAGE_BUFFERS, XN_SENSOR_READ_THREAD_TIMEOUT, XnDeviceSensorProtocolUsbEpCb, GetHelper()->GetPrivateData()->pSpecificImageUsb); + XN_IS_STATUS_OK(nRetVal); + } + else + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "Shutting down USB image read thread..."); + xnUSBShutdownReadThread(GetHelper()->GetPrivateData()->pSpecificImageUsb->pUsbConnection->UsbEp); + } + + nRetVal = m_ActualRead.UnsafeUpdateValue(bRead); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::OpenStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_COLOR); + XN_IS_STATUS_OK(nRetVal); + + // Cropping + if (m_FirmwareCropEnabled.GetValue() == TRUE) + { + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropSizeY)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetX)); + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropOffsetY)); + } + XN_IS_STATUS_OK(m_Helper.ConfigureFirmware(m_FirmwareCropEnabled)); + + nRetVal = XnImageStream::Open(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::CloseStreamImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = GetFirmwareParams()->m_Stream0Mode.SetValue(XN_VIDEO_STREAM_OFF); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnImageStream::Close(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = SetActualRead(FALSE); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetOutputFormat(XnOutputFormats nOutputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nOutputFormat) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + case XN_OUTPUT_FORMAT_YUV422: + case XN_OUTPUT_FORMAT_RGB24: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unsupported image output format: %d", nOutputFormat); + } + + nRetVal = m_Helper.BeforeSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnImageStream::SetOutputFormat(nOutputFormat); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingDataProcessorProperty(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetMirror(XnBool bIsMirrored) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // set firmware mirror + XnBool bFirmwareMirror = (bIsMirrored == TRUE && m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_0); + + xnOSEnterCriticalSection(GetLock()); + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareMirror, bFirmwareMirror); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + // update prop + nRetVal = XnImageStream::SetMirror(bIsMirrored); + xnOSLeaveCriticalSection(GetLock()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetFPS(XnUInt32 nFPS) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.BeforeSettingFirmwareParam(FPSProperty(), nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnImageStream::SetFPS(nFPS); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(FPSProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetResolution(XnResolutions nResolution) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (nResolution) + { + case XN_RESOLUTION_QVGA: + case XN_RESOLUTION_VGA: + case XN_RESOLUTION_SXGA: + case XN_RESOLUTION_UXGA: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown resolution: %u", nResolution); + } + + nRetVal = m_Helper.BeforeSettingFirmwareParam(ResolutionProperty(), nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnImageStream::SetResolution(nResolution); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_Helper.AfterSettingFirmwareParam(ResolutionProperty()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetInputFormat(XnIOImageFormats nInputFormat) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // validity checks + switch (nInputFormat) + { + case XN_IO_IMAGE_FORMAT_YUV422: + case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: + case XN_IO_IMAGE_FORMAT_JPEG: + case XN_IO_IMAGE_FORMAT_BAYER: + case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER: + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Unknown image input format: %d", nInputFormat); + } + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_InputFormat, nInputFormat); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetAntiFlicker(XnUInt32 nFrequency) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_Helper.SimpleSetFirmwareParam(m_AntiFlicker, nFrequency); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetImageQuality(XnUInt32 nQuality) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check relevance + if (m_InputFormat.GetValue() != XN_IO_IMAGE_FORMAT_JPEG) + { + XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_UNSUPPORTED_PARAMETER, XN_MASK_DEVICE_SENSOR, "Image quality is only supported when input format is JPEG"); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::SetCropping(const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = ValidateCropping(pCropping); + XN_IS_STATUS_OK(nRetVal); + + xnOSEnterCriticalSection(GetLock()); + + if (m_Helper.GetFirmwareVersion() > XN_SENSOR_FW_VER_3_0) + { + nRetVal = m_Helper.StartFirmwareTransaction(); + if (nRetVal != XN_STATUS_OK) + { + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + if (pCropping->bEnabled) + { + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeX, pCropping->nXSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropSizeY, pCropping->nYSize); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetX, pCropping->nXOffset); + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropOffsetY, pCropping->nYOffset); + } + + if (nRetVal == XN_STATUS_OK) + nRetVal = m_Helper.SimpleSetFirmwareParam(m_FirmwareCropEnabled, pCropping->bEnabled); + + if (nRetVal != XN_STATUS_OK) + { + m_Helper.RollbackFirmwareTransaction(); + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + + nRetVal = m_Helper.CommitFirmwareTransactionAsBatch(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.UpdateFromFirmware(m_FirmwareCropEnabled); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetX); + m_Helper.UpdateFromFirmware(m_FirmwareCropOffsetY); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeX); + m_Helper.UpdateFromFirmware(m_FirmwareCropSizeY); + xnOSLeaveCriticalSection(GetLock()); + return (nRetVal); + } + } + + nRetVal = XnImageStream::SetCropping(pCropping); + xnOSLeaveCriticalSection(GetLock()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::PostProcessFrame(XnStreamData* pFrameData) +{ + XnStatus nRetVal = XN_STATUS_OK; + + m_Helper.GetFPS()->MarkOutputImage(pFrameData->nFrameID, pFrameData->nTimestamp); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::ReallocTripleFrameBuffer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (IsOpen()) + { + // before actually replacing buffer, lock the processor (so it will not continue to + // use old buffer) + nRetVal = m_Helper.GetFirmware()->GetStreams()->LockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = XnImageStream::ReallocTripleFrameBuffer(); + if (nRetVal != XN_STATUS_OK) + { + m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + return (nRetVal); + } + + if (IsOpen()) + { + nRetVal = m_Helper.GetFirmware()->GetStreams()->UnlockStreamProcessor(GetType(), this); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // if firmware cropping is disabled, crop + if (m_FirmwareCropEnabled.GetValue() == FALSE) + { + nRetVal = XnImageStream::CropImpl(pStreamOutput, pCropping); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorImageStream::Mirror(XnStreamData* pStreamOutput) const +{ + XnStatus nRetVal = XN_STATUS_OK; + + // only perform mirror if it's our job. if mirror is performed by FW, we don't need to do anything. + if (m_FirmwareMirror.GetValue() == FALSE) + { + nRetVal = XnImageStream::Mirror(pStreamOutput); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnUInt32 XnSensorImageStream::CalculateExpectedSize() +{ + XnUInt32 nExpectedImageBufferSize = GetXRes() * GetYRes(); + + // when cropping is turned on, actual IR size is smaller + const XnCropping* pCropping = GetCropping(); + if (pCropping->bEnabled) + { + nExpectedImageBufferSize = pCropping->nXSize * pCropping->nYSize; + } + + switch (m_InputFormat.GetValue()) + { + case XN_IO_IMAGE_FORMAT_YUV422: + case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: + // in YUV each pixel is represented in 2 bytes (actually 2 pixels are represented by 4 bytes) + nExpectedImageBufferSize *= 2; + break; + case XN_IO_IMAGE_FORMAT_BAYER: + // each pixel is one byte. + break; + case XN_IO_IMAGE_FORMAT_JPEG: + // image should be in RGB now - 3 bytes a pixel + nExpectedImageBufferSize *= 3; + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Does not know to calculate expected size for input format %d", m_InputFormat.GetValue()); + } + + return nExpectedImageBufferSize; +} + +XnStatus XnSensorImageStream::CreateDataProcessor(XnDataProcessor** ppProcessor) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnStreamProcessor* pNew; + + switch (m_InputFormat.GetValue()) + { + case XN_IO_IMAGE_FORMAT_BAYER: + XN_VALIDATE_NEW_AND_INIT(pNew, XnBayerImageProcessor, this, &m_Helper); + break; + case XN_IO_IMAGE_FORMAT_YUV422: + XN_VALIDATE_NEW_AND_INIT(pNew, XnPSCompressedImageProcessor, this, &m_Helper); + break; + case XN_IO_IMAGE_FORMAT_JPEG: + XN_VALIDATE_NEW_AND_INIT(pNew, XnJpegImageProcessor, this, &m_Helper); + break; + case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_YUV422: + if (GetOutputFormat() == XN_OUTPUT_FORMAT_YUV422) + { + XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedYUVImageProcessor, this, &m_Helper); + } + else if (GetOutputFormat() == XN_OUTPUT_FORMAT_RGB24) + { + XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedYUVtoRGBImageProcessor, this, &m_Helper); + } + else + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "invalid ouput format %d!", GetOutputFormat()); + } + break; + case XN_IO_IMAGE_FORMAT_UNCOMPRESSED_BAYER: + XN_VALIDATE_NEW_AND_INIT(pNew, XnUncompressedBayerProcessor, this, &m_Helper); + break; + default: + return XN_STATUS_IO_INVALID_STREAM_IMAGE_FORMAT; + } + + *ppProcessor = pNew; + + return XN_STATUS_OK; +} + +XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; + return pThis->SetInputFormat((XnIOImageFormats)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetAntiFlickerCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; + return pThis->SetAntiFlicker((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetImageQualityCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; + return pThis->SetImageQuality((XnUInt32)nValue); +} + +XnStatus XN_CALLBACK_TYPE XnSensorImageStream::SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + XnSensorImageStream* pThis = (XnSensorImageStream*)pCookie; + return pThis->SetActualRead(nValue == TRUE); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorImageStream.h b/Source/XnDeviceSensorV2/XnSensorImageStream.h index 526da72..c661086 100644 --- a/Source/XnDeviceSensorV2/XnSensorImageStream.h +++ b/Source/XnDeviceSensorV2/XnSensorImageStream.h @@ -1,124 +1,124 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_IMAGE_STREAM_H__ -#define __XN_SENSOR_IMAGE_STREAM_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensorStreamHelper.h" -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// XnSensorImageStream class -//--------------------------------------------------------------------------- -class XnSensorImageStream : public XnImageStream, public IXnSensorStream -{ -public: - XnSensorImageStream(const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); - ~XnSensorImageStream() { Free(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Init(); - XnStatus Free(); - XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } - - XnUInt32 CalculateExpectedSize(); - - inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } - - friend class XnImageProcessor; - -protected: - inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } - - //--------------------------------------------------------------------------- - // Overridden Methods - //--------------------------------------------------------------------------- - XnStatus Open() { return m_Helper.Open(); } - XnStatus Close() { return m_Helper.Close(); } - XnStatus PostProcessFrame(XnStreamData* pFrameData); - XnStatus ReallocTripleFrameBuffer(); - XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); - XnStatus Mirror(XnStreamData* pStreamOutput) const; - XnStatus ConfigureStreamImpl(); - XnStatus OpenStreamImpl(); - XnStatus CloseStreamImpl(); - XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); - XnStatus MapPropertiesToFirmware(); - void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } - XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } - XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } - - //--------------------------------------------------------------------------- - // Setters - //--------------------------------------------------------------------------- - XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); - XnStatus SetMirror(XnBool bIsMirrored); - XnStatus SetResolution(XnResolutions nResolution); - XnStatus SetFPS(XnUInt32 nFPS); - virtual XnStatus SetInputFormat(XnIOImageFormats nInputFormat); - virtual XnStatus SetAntiFlicker(XnUInt32 nFrequency); - virtual XnStatus SetImageQuality(XnUInt32 nQuality); - XnStatus SetCropping(const XnCropping* pCropping); - XnStatus SetActualRead(XnBool bRead); - -private: - XnStatus ValidateMode(); - static XnUInt32 GetMaxBufferSize(XnFWVer version); - - static XnStatus XN_CALLBACK_TYPE SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetAntiFlickerCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetImageQualityCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - //--------------------------------------------------------------------------- - // Members - //--------------------------------------------------------------------------- - XnSensorStreamHelper m_Helper; - XnSharedMemoryBufferPool m_BufferPool; - - XnActualStringProperty m_SharedBufferName; - XnActualIntProperty m_InputFormat; - XnActualIntProperty m_AntiFlicker; - XnActualIntProperty m_ImageQuality; - - XnActualIntProperty m_FirmwareMirror; - - XnActualIntProperty m_FirmwareCropSizeX; - XnActualIntProperty m_FirmwareCropSizeY; - XnActualIntProperty m_FirmwareCropOffsetX; - XnActualIntProperty m_FirmwareCropOffsetY; - XnActualIntProperty m_FirmwareCropEnabled; - - XnActualIntProperty m_ActualRead; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_IMAGE_STREAM_H__ +#define __XN_SENSOR_IMAGE_STREAM_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensorStreamHelper.h" +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// XnSensorImageStream class +//--------------------------------------------------------------------------- +class XnSensorImageStream : public XnImageStream, public IXnSensorStream +{ +public: + XnSensorImageStream(const XnChar* strDeviceName, const XnChar* StreamName, XnSensorObjects* pObjects, XnUInt32 nBufferCount); + ~XnSensorImageStream() { Free(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Init(); + XnStatus Free(); + XnStatus BatchConfig(const XnActualPropertiesHash& props) { return m_Helper.BatchConfig(props); } + + XnUInt32 CalculateExpectedSize(); + + inline XnSensorStreamHelper* GetHelper() { return &m_Helper; } + + friend class XnImageProcessor; + +protected: + inline XnSensorFirmwareParams* GetFirmwareParams() const { return m_Helper.GetFirmware()->GetParams(); } + + //--------------------------------------------------------------------------- + // Overridden Methods + //--------------------------------------------------------------------------- + XnStatus Open() { return m_Helper.Open(); } + XnStatus Close() { return m_Helper.Close(); } + XnStatus PostProcessFrame(XnStreamData* pFrameData); + XnStatus ReallocTripleFrameBuffer(); + XnStatus CropImpl(XnStreamData* pStreamOutput, const XnCropping* pCropping); + XnStatus Mirror(XnStreamData* pStreamOutput) const; + XnStatus ConfigureStreamImpl(); + XnStatus OpenStreamImpl(); + XnStatus CloseStreamImpl(); + XnStatus CreateDataProcessor(XnDataProcessor** ppProcessor); + XnStatus MapPropertiesToFirmware(); + void GetFirmwareStreamConfig(XnResolutions* pnRes, XnUInt32* pnFPS) { *pnRes = GetResolution(); *pnFPS = GetFPS(); } + XnStatus WriteImpl(XnStreamData* pStreamData) { return XN_STATUS_DEVICE_UNSUPPORTED_MODE; } + XnSharedMemoryBufferPool* GetSharedMemoryBuffer() { return &m_BufferPool; } + + //--------------------------------------------------------------------------- + // Setters + //--------------------------------------------------------------------------- + XnStatus SetOutputFormat(XnOutputFormats nOutputFormat); + XnStatus SetMirror(XnBool bIsMirrored); + XnStatus SetResolution(XnResolutions nResolution); + XnStatus SetFPS(XnUInt32 nFPS); + virtual XnStatus SetInputFormat(XnIOImageFormats nInputFormat); + virtual XnStatus SetAntiFlicker(XnUInt32 nFrequency); + virtual XnStatus SetImageQuality(XnUInt32 nQuality); + XnStatus SetCropping(const XnCropping* pCropping); + XnStatus SetActualRead(XnBool bRead); + +private: + XnStatus ValidateMode(); + static XnUInt32 GetMaxBufferSize(XnFWVer version); + + static XnStatus XN_CALLBACK_TYPE SetInputFormatCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetAntiFlickerCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetImageQualityCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + static XnStatus XN_CALLBACK_TYPE SetActualReadCallback(XnActualIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + //--------------------------------------------------------------------------- + // Members + //--------------------------------------------------------------------------- + XnSensorStreamHelper m_Helper; + XnSharedMemoryBufferPool m_BufferPool; + + XnActualStringProperty m_SharedBufferName; + XnActualIntProperty m_InputFormat; + XnActualIntProperty m_AntiFlicker; + XnActualIntProperty m_ImageQuality; + + XnActualIntProperty m_FirmwareMirror; + + XnActualIntProperty m_FirmwareCropSizeX; + XnActualIntProperty m_FirmwareCropSizeY; + XnActualIntProperty m_FirmwareCropOffsetX; + XnActualIntProperty m_FirmwareCropOffsetY; + XnActualIntProperty m_FirmwareCropEnabled; + + XnActualIntProperty m_ActualRead; +}; + #endif //__XN_SENSOR_IMAGE_STREAM_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorMapGenerator.cpp b/Source/XnDeviceSensorV2/XnSensorMapGenerator.cpp index 047dce3..9c5447e 100644 --- a/Source/XnDeviceSensorV2/XnSensorMapGenerator.cpp +++ b/Source/XnDeviceSensorV2/XnSensorMapGenerator.cpp @@ -1,215 +1,215 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorMapGenerator.h" - -//--------------------------------------------------------------------------- -// XnSensorMapGenerator class -//--------------------------------------------------------------------------- -XnSensorMapGenerator::XnSensorMapGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : - XnSensorGenerator(context, sensor, pSensor, strStreamName) -{} - -XnStatus XnSensorMapGenerator::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnSensorGenerator::Init(); - XN_IS_STATUS_OK(nRetVal); - - XnMapOutputMode mode; - - // QVGA 30 - mode.nXRes = XN_QVGA_X_RES; - mode.nYRes = XN_QVGA_Y_RES; - mode.nFPS = 30; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - - // QVGA 60 - mode.nXRes = XN_QVGA_X_RES; - mode.nYRes = XN_QVGA_Y_RES; - mode.nFPS = 60; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - - // VGA 30 - mode.nXRes = XN_VGA_X_RES; - mode.nYRes = XN_VGA_Y_RES; - mode.nFPS = 30; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - - if (m_Version.FWVer >= XN_SENSOR_FW_VER_5_2) - { - // QVGA 25 - mode.nXRes = XN_QVGA_X_RES; - mode.nYRes = XN_QVGA_Y_RES; - mode.nFPS = 25; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - - // VGA 25 - mode.nXRes = XN_VGA_X_RES; - mode.nYRes = XN_VGA_Y_RES; - mode.nFPS = 25; - nRetVal = m_SupportedModes.AddLast(mode); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnBool XnSensorMapGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return (strcmp(strCapabilityName, XN_CAPABILITY_CROPPING) == 0 || - XnSensorGenerator::IsCapabilitySupported(strCapabilityName)); -} - -XnUInt32 XnSensorMapGenerator::GetSupportedMapOutputModesCount() -{ - return m_SupportedModes.Size(); -} - -XnStatus XnSensorMapGenerator::GetSupportedMapOutputModes(XnMapOutputMode aModes[], XnUInt32& nCount) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(aModes); - - if (nCount < m_SupportedModes.Size()) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - XnUInt32 i = 0; - for (XnMapOutputModeList::Iterator it = m_SupportedModes.begin(); it != m_SupportedModes.end(); ++it, ++i) - { - aModes[i] = *it; - } - - nCount = m_SupportedModes.Size(); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorMapGenerator::SetMapOutputMode(const XnMapOutputMode& Mode) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnMapOutputMode current; - GetMapOutputMode(current); - - if (current.nFPS == Mode.nFPS && - current.nXRes == Mode.nXRes && - current.nYRes == Mode.nYRes) - { - return (XN_STATUS_OK); - } - - XN_PROPERTY_SET_CREATE_ON_STACK(props); - XnPropertySetAddModule(&props, m_strModule); - XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_X_RES, Mode.nXRes); - XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_Y_RES, Mode.nYRes); - XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_FPS, Mode.nFPS); - - nRetVal = m_pSensor->BatchConfig(&props); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorMapGenerator::GetMapOutputMode(XnMapOutputMode& OutputMode) -{ - XnUInt64 nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_X_RES, &nValue); - OutputMode.nXRes = (XnUInt32)nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_Y_RES, &nValue); - OutputMode.nYRes = (XnUInt32)nValue; - m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_FPS, &nValue); - OutputMode.nFPS = (XnUInt32)nValue; - - return XN_STATUS_OK; -} - -XnStatus XnSensorMapGenerator::RegisterToMapOutputModeChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - // don't register to xRes and yRes. If we did so, we would get two notifications when - // resolution changed. - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_RESOLUTION, - XN_STREAM_PROPERTY_FPS, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorMapGenerator::UnregisterFromMapOutputModeChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -XnStatus XnSensorMapGenerator::SetCropping(const XnCropping &Cropping) -{ - XnGeneralBuffer gbValue = XnGeneralBufferPack((void*)&Cropping, sizeof(Cropping)); - return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_CROPPING, gbValue); -} - -XnStatus XnSensorMapGenerator::GetCropping(XnCropping &Cropping) -{ - return m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_CROPPING, XN_PACK_GENERAL_BUFFER(Cropping)); -} - -XnStatus XnSensorMapGenerator::RegisterToCroppingChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_STREAM_PROPERTY_CROPPING, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorMapGenerator::UnregisterFromCroppingChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorMapGenerator::FilterProperties(XnActualPropertiesHash* pHash) -{ - XnSensorGenerator::FilterProperties(pHash); - pHash->Remove(XN_STREAM_PROPERTY_X_RES); - pHash->Remove(XN_STREAM_PROPERTY_Y_RES); - pHash->Remove(XN_STREAM_PROPERTY_FPS); - pHash->Remove(XN_STREAM_PROPERTY_CROPPING); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorMapGenerator.h" + +//--------------------------------------------------------------------------- +// XnSensorMapGenerator class +//--------------------------------------------------------------------------- +XnSensorMapGenerator::XnSensorMapGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName) : + XnSensorGenerator(context, sensor, pSensor, strStreamName) +{} + +XnStatus XnSensorMapGenerator::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnSensorGenerator::Init(); + XN_IS_STATUS_OK(nRetVal); + + XnMapOutputMode mode; + + // QVGA 30 + mode.nXRes = XN_QVGA_X_RES; + mode.nYRes = XN_QVGA_Y_RES; + mode.nFPS = 30; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + + // QVGA 60 + mode.nXRes = XN_QVGA_X_RES; + mode.nYRes = XN_QVGA_Y_RES; + mode.nFPS = 60; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + + // VGA 30 + mode.nXRes = XN_VGA_X_RES; + mode.nYRes = XN_VGA_Y_RES; + mode.nFPS = 30; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + + if (m_Version.FWVer >= XN_SENSOR_FW_VER_5_2) + { + // QVGA 25 + mode.nXRes = XN_QVGA_X_RES; + mode.nYRes = XN_QVGA_Y_RES; + mode.nFPS = 25; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + + // VGA 25 + mode.nXRes = XN_VGA_X_RES; + mode.nYRes = XN_VGA_Y_RES; + mode.nFPS = 25; + nRetVal = m_SupportedModes.AddLast(mode); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnBool XnSensorMapGenerator::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return (strcmp(strCapabilityName, XN_CAPABILITY_CROPPING) == 0 || + XnSensorGenerator::IsCapabilitySupported(strCapabilityName)); +} + +XnUInt32 XnSensorMapGenerator::GetSupportedMapOutputModesCount() +{ + return m_SupportedModes.Size(); +} + +XnStatus XnSensorMapGenerator::GetSupportedMapOutputModes(XnMapOutputMode aModes[], XnUInt32& nCount) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(aModes); + + if (nCount < m_SupportedModes.Size()) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + XnUInt32 i = 0; + for (XnMapOutputModeList::Iterator it = m_SupportedModes.begin(); it != m_SupportedModes.end(); ++it, ++i) + { + aModes[i] = *it; + } + + nCount = m_SupportedModes.Size(); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorMapGenerator::SetMapOutputMode(const XnMapOutputMode& Mode) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnMapOutputMode current; + GetMapOutputMode(current); + + if (current.nFPS == Mode.nFPS && + current.nXRes == Mode.nXRes && + current.nYRes == Mode.nYRes) + { + return (XN_STATUS_OK); + } + + XN_PROPERTY_SET_CREATE_ON_STACK(props); + XnPropertySetAddModule(&props, m_strModule); + XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_X_RES, Mode.nXRes); + XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_Y_RES, Mode.nYRes); + XnPropertySetAddIntProperty(&props, m_strModule, XN_STREAM_PROPERTY_FPS, Mode.nFPS); + + nRetVal = m_pSensor->BatchConfig(&props); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorMapGenerator::GetMapOutputMode(XnMapOutputMode& OutputMode) +{ + XnUInt64 nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_X_RES, &nValue); + OutputMode.nXRes = (XnUInt32)nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_Y_RES, &nValue); + OutputMode.nYRes = (XnUInt32)nValue; + m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_FPS, &nValue); + OutputMode.nFPS = (XnUInt32)nValue; + + return XN_STATUS_OK; +} + +XnStatus XnSensorMapGenerator::RegisterToMapOutputModeChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + // don't register to xRes and yRes. If we did so, we would get two notifications when + // resolution changed. + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_RESOLUTION, + XN_STREAM_PROPERTY_FPS, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorMapGenerator::UnregisterFromMapOutputModeChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +XnStatus XnSensorMapGenerator::SetCropping(const XnCropping &Cropping) +{ + XnGeneralBuffer gbValue = XnGeneralBufferPack((void*)&Cropping, sizeof(Cropping)); + return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_CROPPING, gbValue); +} + +XnStatus XnSensorMapGenerator::GetCropping(XnCropping &Cropping) +{ + return m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_CROPPING, XN_PACK_GENERAL_BUFFER(Cropping)); +} + +XnStatus XnSensorMapGenerator::RegisterToCroppingChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_STREAM_PROPERTY_CROPPING, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorMapGenerator::UnregisterFromCroppingChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorMapGenerator::FilterProperties(XnActualPropertiesHash* pHash) +{ + XnSensorGenerator::FilterProperties(pHash); + pHash->Remove(XN_STREAM_PROPERTY_X_RES); + pHash->Remove(XN_STREAM_PROPERTY_Y_RES); + pHash->Remove(XN_STREAM_PROPERTY_FPS); + pHash->Remove(XN_STREAM_PROPERTY_CROPPING); +} diff --git a/Source/XnDeviceSensorV2/XnSensorMapGenerator.h b/Source/XnDeviceSensorV2/XnSensorMapGenerator.h index 05af932..96b6f63 100644 --- a/Source/XnDeviceSensorV2/XnSensorMapGenerator.h +++ b/Source/XnDeviceSensorV2/XnSensorMapGenerator.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_MAP_GENERATOR_H__ -#define __XN_SENSOR_MAP_GENERATOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorGenerator.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorMapGenerator : - public XnSensorGenerator, - virtual public xn::ModuleMapGenerator, - virtual public xn::ModuleCroppingInterface -{ -public: - XnSensorMapGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); - - XnStatus Init(); - - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - - XnUInt32 GetSupportedMapOutputModesCount(); - XnStatus GetSupportedMapOutputModes(XnMapOutputMode aModes[], XnUInt32& nCount); - - XnStatus SetMapOutputMode(const XnMapOutputMode& Mode); - XnStatus GetMapOutputMode(XnMapOutputMode& Mode); - XnStatus RegisterToMapOutputModeChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromMapOutputModeChange(XnCallbackHandle hCallback); - - xn::ModuleCroppingInterface* GetCroppingInterface() { return this; } - XnStatus SetCropping(const XnCropping &Cropping); - XnStatus GetCropping(XnCropping &Cropping); - XnStatus RegisterToCroppingChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromCroppingChange(XnCallbackHandle hCallback); - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); - - XN_DECLARE_LIST(XnMapOutputMode, XnMapOutputModeList); - - XnMapOutputModeList m_SupportedModes; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_MAP_GENERATOR_H__ +#define __XN_SENSOR_MAP_GENERATOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorGenerator.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorMapGenerator : + public XnSensorGenerator, + virtual public xn::ModuleMapGenerator, + virtual public xn::ModuleCroppingInterface +{ +public: + XnSensorMapGenerator(xn::Context& context, xn::Device& sensor, XnDeviceBase* pSensor, const XnChar* strStreamName); + + XnStatus Init(); + + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + + XnUInt32 GetSupportedMapOutputModesCount(); + XnStatus GetSupportedMapOutputModes(XnMapOutputMode aModes[], XnUInt32& nCount); + + XnStatus SetMapOutputMode(const XnMapOutputMode& Mode); + XnStatus GetMapOutputMode(XnMapOutputMode& Mode); + XnStatus RegisterToMapOutputModeChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromMapOutputModeChange(XnCallbackHandle hCallback); + + xn::ModuleCroppingInterface* GetCroppingInterface() { return this; } + XnStatus SetCropping(const XnCropping &Cropping); + XnStatus GetCropping(XnCropping &Cropping); + XnStatus RegisterToCroppingChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromCroppingChange(XnCallbackHandle hCallback); + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); + + XN_DECLARE_LIST(XnMapOutputMode, XnMapOutputModeList); + + XnMapOutputModeList m_SupportedModes; +}; + #endif // __XN_SENSOR_MAP_GENERATOR_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorOpenNiteImpl.cpp b/Source/XnDeviceSensorV2/XnSensorOpenNiteImpl.cpp index fb6c55b..caf4917 100644 --- a/Source/XnDeviceSensorV2/XnSensorOpenNiteImpl.cpp +++ b/Source/XnDeviceSensorV2/XnSensorOpenNiteImpl.cpp @@ -1,57 +1,57 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnExportedSensorDevice.h" -#include "XnSensorDepthGenerator.h" -#include "XnSensorImageGenerator.h" -#include "XnSensorIRGenerator.h" -#include "XnSensorAudioGenerator.h" -#include "XnSensorClient.h" - -//--------------------------------------------------------------------------- -// Exporting -//--------------------------------------------------------------------------- - -class SensorModule : public xn::Module -{ - XnStatus Load() - { - return XnSensorClient::TakeServerLocation(); - } -}; - -XN_EXPORT_MODULE(SensorModule) -XN_EXPORT_DEVICE(XnExportedSensorDevice) -XN_EXPORT_DEPTH(XnExportedSensorDepthGenerator) -XN_EXPORT_IMAGE(XnExportedSensorImageGenerator) -XN_EXPORT_IR(XnExportedSensorIRGenerator) -XN_EXPORT_AUDIO(XnExportedSensorAudioGenerator) - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnExportedSensorDevice.h" +#include "XnSensorDepthGenerator.h" +#include "XnSensorImageGenerator.h" +#include "XnSensorIRGenerator.h" +#include "XnSensorAudioGenerator.h" +#include "XnSensorClient.h" + +//--------------------------------------------------------------------------- +// Exporting +//--------------------------------------------------------------------------- + +class SensorModule : public xn::Module +{ + XnStatus Load() + { + return XnSensorClient::TakeServerLocation(); + } +}; + +XN_EXPORT_MODULE(SensorModule) +XN_EXPORT_DEVICE(XnExportedSensorDevice) +XN_EXPORT_DEPTH(XnExportedSensorDepthGenerator) +XN_EXPORT_IMAGE(XnExportedSensorImageGenerator) +XN_EXPORT_IR(XnExportedSensorIRGenerator) +XN_EXPORT_AUDIO(XnExportedSensorAudioGenerator) + diff --git a/Source/XnDeviceSensorV2/XnSensorProductionNode.cpp b/Source/XnDeviceSensorV2/XnSensorProductionNode.cpp index 4cbd493..3876e8f 100644 --- a/Source/XnDeviceSensorV2/XnSensorProductionNode.cpp +++ b/Source/XnDeviceSensorV2/XnSensorProductionNode.cpp @@ -1,244 +1,249 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorProductionNode.h" -#include "XnMultiPropChangedHandler.h" - -//--------------------------------------------------------------------------- -// XnSensorProductionNode class -//--------------------------------------------------------------------------- -XnSensorProductionNode::XnSensorProductionNode(xn::Context& context, const XnChar* strInstanceName, XnDeviceBase* pSensor, const XnChar* strModuleName) : - m_Context(context), - m_pSensor(pSensor), - m_pNotifications(NULL) -{ - strcpy(m_strInstanceName, strInstanceName); - strcpy(m_strModule, strModuleName); -} - -XnSensorProductionNode::~XnSensorProductionNode() -{ - // free all memory allocated for registration, even if client did not unregister from it - for (XnMultiPropChangedHandlerHash::Iterator it = m_AllHandlers.begin(); it != m_AllHandlers.end(); ++it) - { - XN_DELETE(it.Key()); - } -} - -XnBool XnSensorProductionNode::IsCapabilitySupported(const XnChar* strCapabilityName) -{ - return ((strcmp(strCapabilityName, XN_CAPABILITY_EXTENDED_SERIALIZATION) == 0) || - (strcmp(strCapabilityName, XN_CAPABILITY_LOCK_AWARE) == 0)); -} - -XnStatus XnSensorProductionNode::SetIntProperty(const XnChar* strName, XnUInt64 nValue) -{ - return m_pSensor->SetProperty(m_strModule, strName, nValue); -} - -XnStatus XnSensorProductionNode::SetRealProperty(const XnChar* strName, XnDouble dValue) -{ - return m_pSensor->SetProperty(m_strModule, strName, dValue); -} - -XnStatus XnSensorProductionNode::SetStringProperty(const XnChar* strName, const XnChar* strValue) -{ - return m_pSensor->SetProperty(m_strModule, strName, strValue); -} - -XnStatus XnSensorProductionNode::SetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, const void* pBuffer) -{ - return m_pSensor->SetProperty(m_strModule, strName, XnGeneralBufferPack((void*)pBuffer, nBufferSize)); -} - -XnStatus XnSensorProductionNode::GetIntProperty(const XnChar* strName, XnUInt64& nValue) const -{ - return m_pSensor->GetProperty(m_strModule, strName, &nValue); -} - -XnStatus XnSensorProductionNode::GetRealProperty(const XnChar* strName, XnDouble& dValue) const -{ - return m_pSensor->GetProperty(m_strModule, strName, &dValue); -} - -XnStatus XnSensorProductionNode::GetStringProperty(const XnChar* strName, XnChar* csValue) const -{ - return m_pSensor->GetProperty(m_strModule, strName, csValue); -} - -XnStatus XnSensorProductionNode::GetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, void* pBuffer) const -{ - return m_pSensor->GetProperty(m_strModule, strName, XnGeneralBufferPack(pBuffer, nBufferSize)); -} - -XnStatus XnSensorProductionNode::SetLockState(XnBool bLocked) -{ - return m_pSensor->SetProperty(m_strModule, XN_MODULE_PROPERTY_LOCK, (XnUInt64)bLocked); -} - -XnBool XnSensorProductionNode::GetLockState() -{ - XnUInt64 nValue = FALSE; - XnStatus nRetVal = m_pSensor->GetProperty(m_strModule, XN_MODULE_PROPERTY_LOCK, &nValue); - return (nValue == TRUE); -} - -XnStatus XnSensorProductionNode::RegisterToLockChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) -{ - const XnChar* aProps[] = - { - XN_MODULE_PROPERTY_LOCK, - NULL - }; - - return RegisterToProps(handler, pCookie, hCallback, aProps); -} - -void XnSensorProductionNode::UnregisterFromLockChange(XnCallbackHandle hCallback) -{ - UnregisterFromProps(hCallback); -} - -void XnSensorProductionNode::FilterProperties(XnActualPropertiesHash* pHash) -{ - pHash->Remove(XN_MODULE_PROPERTY_LOCK); -} - -XnStatus XnSensorProductionNode::NotifyExState(XnNodeNotifications* pNotifications, void* pCookie) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get all properties - XN_PROPERTY_SET_CREATE_ON_STACK(props); - nRetVal = m_pSensor->GetAllProperties(&props, FALSE, GetModuleName()); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pPropsHash = props.pData->begin().Value(); - - // filter properties (remove the ones already exposed as OpenNI interfaces) - FilterProperties(pPropsHash); - - const XnChar* astrIntProps[200] = {0}; - const XnChar* astrRealProps[200] = {0}; - const XnChar* astrStringProps[200] = {0}; - const XnChar* astrGeneralProps[200] = {0}; - - XnUInt32 nIntProps = 0; - XnUInt32 nRealProps = 0; - XnUInt32 nStringProps = 0; - XnUInt32 nGeneralProps = 0; - - // enumerate over properties - for (XnActualPropertiesHash::Iterator it = pPropsHash->begin(); it != pPropsHash->end(); ++it) - { - XnProperty* pProp = it.Value(); - - switch (pProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; - pNotifications->OnNodeIntPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pIntProp->GetValue()); - astrIntProps[nIntProps++] = pProp->GetName(); - } - break; - case XN_PROPERTY_TYPE_REAL: - { - XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; - pNotifications->OnNodeRealPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pRealProp->GetValue()); - astrRealProps[nRealProps++] = pProp->GetName(); - } - break; - case XN_PROPERTY_TYPE_STRING: - { - XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; - pNotifications->OnNodeStringPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pStrProp->GetValue()); - astrStringProps[nStringProps++] = pProp->GetName(); - } - break; - case XN_PROPERTY_TYPE_GENERAL: - { - XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; - pNotifications->OnNodeGeneralPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pGenProp->GetValue().nDataSize, pGenProp->GetValue().pData); - astrGeneralProps[nGeneralProps++] = pProp->GetName(); - } - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Unknown property type: %d", pProp->GetType()); - } - } - - // TODO: also register to these properties, and if changed, notify. - - // store notifications object - m_pNotifications = pNotifications; - m_pCookie = pCookie; - - return (XN_STATUS_OK); -} -void XnSensorProductionNode::UnregisterExNotifications() -{ - // TODO: unregister from props - - // reset notifications object - m_pNotifications = NULL; - m_pCookie = NULL; -} - -XnStatus XnSensorProductionNode::RegisterToProps(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback, const XnChar** strNames, const XnChar* strModule /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnMultiPropStateChangedHandler* pHandler; - XN_VALIDATE_NEW(pHandler, XnMultiPropStateChangedHandler, this, handler, pCookie, strModule); - - nRetVal = pHandler->AddProperties(strNames); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pHandler); - return (nRetVal); - } - - // register it for later deletion - m_AllHandlers.Set(pHandler, pHandler); - - hCallback = (XnCallbackHandle)pHandler; - - return (XN_STATUS_OK); -} - -void XnSensorProductionNode::UnregisterFromProps(XnCallbackHandle hCallback) -{ - XnMultiPropStateChangedHandler* pHandler = (XnMultiPropStateChangedHandler*)hCallback; - m_AllHandlers.Remove(pHandler); - pHandler->Unregister(); - XN_DELETE(pHandler); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorProductionNode.h" +#include "XnMultiPropChangedHandler.h" + +//--------------------------------------------------------------------------- +// XnSensorProductionNode class +//--------------------------------------------------------------------------- +XnSensorProductionNode::XnSensorProductionNode(xn::Context& context, const XnChar* strInstanceName, XnDeviceBase* pSensor, const XnChar* strModuleName) : + m_Context(context), + m_pSensor(pSensor), + m_pNotifications(NULL) +{ + strcpy(m_strInstanceName, strInstanceName); + strcpy(m_strModule, strModuleName); +} + +XnSensorProductionNode::~XnSensorProductionNode() +{ + // free all memory allocated for registration, even if client did not unregister from it + for (XnMultiPropChangedHandlerHash::Iterator it = m_AllHandlers.begin(); it != m_AllHandlers.end(); ++it) + { + XN_DELETE(it.Key()); + } +} + +XnBool XnSensorProductionNode::IsCapabilitySupported(const XnChar* strCapabilityName) +{ + return ((strcmp(strCapabilityName, XN_CAPABILITY_EXTENDED_SERIALIZATION) == 0) || + (strcmp(strCapabilityName, XN_CAPABILITY_LOCK_AWARE) == 0)); +} + +XnStatus XnSensorProductionNode::SetIntProperty(const XnChar* strName, XnUInt64 nValue) +{ + return m_pSensor->SetProperty(m_strModule, strName, nValue); +} + +XnStatus XnSensorProductionNode::SetRealProperty(const XnChar* strName, XnDouble dValue) +{ + return m_pSensor->SetProperty(m_strModule, strName, dValue); +} + +XnStatus XnSensorProductionNode::SetStringProperty(const XnChar* strName, const XnChar* strValue) +{ + return m_pSensor->SetProperty(m_strModule, strName, strValue); +} + +XnStatus XnSensorProductionNode::SetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, const void* pBuffer) +{ + return m_pSensor->SetProperty(m_strModule, strName, XnGeneralBufferPack((void*)pBuffer, nBufferSize)); +} + +XnStatus XnSensorProductionNode::GetIntProperty(const XnChar* strName, XnUInt64& nValue) const +{ + return m_pSensor->GetProperty(m_strModule, strName, &nValue); +} + +XnStatus XnSensorProductionNode::GetRealProperty(const XnChar* strName, XnDouble& dValue) const +{ + return m_pSensor->GetProperty(m_strModule, strName, &dValue); +} + +XnStatus XnSensorProductionNode::GetStringProperty(const XnChar* strName, XnChar* csValue, XnUInt32 nBufSize) const +{ + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + XnStatus nRetVal = m_pSensor->GetProperty(m_strModule, strName, strValue); + XN_IS_STATUS_OK(nRetVal); + nRetVal = xnOSStrCopy(csValue, strValue, nBufSize); + XN_IS_STATUS_OK(nRetVal); + return XN_STATUS_OK; +} + +XnStatus XnSensorProductionNode::GetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, void* pBuffer) const +{ + return m_pSensor->GetProperty(m_strModule, strName, XnGeneralBufferPack(pBuffer, nBufferSize)); +} + +XnStatus XnSensorProductionNode::SetLockState(XnBool bLocked) +{ + return m_pSensor->SetProperty(m_strModule, XN_MODULE_PROPERTY_LOCK, (XnUInt64)bLocked); +} + +XnBool XnSensorProductionNode::GetLockState() +{ + XnUInt64 nValue = FALSE; + XnStatus nRetVal = m_pSensor->GetProperty(m_strModule, XN_MODULE_PROPERTY_LOCK, &nValue); + return (nValue == TRUE); +} + +XnStatus XnSensorProductionNode::RegisterToLockChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) +{ + const XnChar* aProps[] = + { + XN_MODULE_PROPERTY_LOCK, + NULL + }; + + return RegisterToProps(handler, pCookie, hCallback, aProps); +} + +void XnSensorProductionNode::UnregisterFromLockChange(XnCallbackHandle hCallback) +{ + UnregisterFromProps(hCallback); +} + +void XnSensorProductionNode::FilterProperties(XnActualPropertiesHash* pHash) +{ + pHash->Remove(XN_MODULE_PROPERTY_LOCK); +} + +XnStatus XnSensorProductionNode::NotifyExState(XnNodeNotifications* pNotifications, void* pCookie) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get all properties + XN_PROPERTY_SET_CREATE_ON_STACK(props); + nRetVal = m_pSensor->GetAllProperties(&props, FALSE, GetModuleName()); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pPropsHash = props.pData->begin().Value(); + + // filter properties (remove the ones already exposed as OpenNI interfaces) + FilterProperties(pPropsHash); + + const XnChar* astrIntProps[200] = {0}; + const XnChar* astrRealProps[200] = {0}; + const XnChar* astrStringProps[200] = {0}; + const XnChar* astrGeneralProps[200] = {0}; + + XnUInt32 nIntProps = 0; + XnUInt32 nRealProps = 0; + XnUInt32 nStringProps = 0; + XnUInt32 nGeneralProps = 0; + + // enumerate over properties + for (XnActualPropertiesHash::Iterator it = pPropsHash->begin(); it != pPropsHash->end(); ++it) + { + XnProperty* pProp = it.Value(); + + switch (pProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; + pNotifications->OnNodeIntPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pIntProp->GetValue()); + astrIntProps[nIntProps++] = pProp->GetName(); + } + break; + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; + pNotifications->OnNodeRealPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pRealProp->GetValue()); + astrRealProps[nRealProps++] = pProp->GetName(); + } + break; + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; + pNotifications->OnNodeStringPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pStrProp->GetValue()); + astrStringProps[nStringProps++] = pProp->GetName(); + } + break; + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; + pNotifications->OnNodeGeneralPropChanged(pCookie, GetInstanceName(), pProp->GetName(), pGenProp->GetValue().nDataSize, pGenProp->GetValue().pData); + astrGeneralProps[nGeneralProps++] = pProp->GetName(); + } + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DEVICE_SENSOR, "Unknown property type: %d", pProp->GetType()); + } + } + + // TODO: also register to these properties, and if changed, notify. + + // store notifications object + m_pNotifications = pNotifications; + m_pCookie = pCookie; + + return (XN_STATUS_OK); +} +void XnSensorProductionNode::UnregisterExNotifications() +{ + // TODO: unregister from props + + // reset notifications object + m_pNotifications = NULL; + m_pCookie = NULL; +} + +XnStatus XnSensorProductionNode::RegisterToProps(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback, const XnChar** strNames, const XnChar* strModule /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnMultiPropStateChangedHandler* pHandler; + XN_VALIDATE_NEW(pHandler, XnMultiPropStateChangedHandler, this, handler, pCookie, strModule); + + nRetVal = pHandler->AddProperties(strNames); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pHandler); + return (nRetVal); + } + + // register it for later deletion + m_AllHandlers.Set(pHandler, pHandler); + + hCallback = (XnCallbackHandle)pHandler; + + return (XN_STATUS_OK); +} + +void XnSensorProductionNode::UnregisterFromProps(XnCallbackHandle hCallback) +{ + XnMultiPropStateChangedHandler* pHandler = (XnMultiPropStateChangedHandler*)hCallback; + m_AllHandlers.Remove(pHandler); + pHandler->Unregister(); + XN_DELETE(pHandler); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorProductionNode.h b/Source/XnDeviceSensorV2/XnSensorProductionNode.h index 19e02ee..55a0160 100644 --- a/Source/XnDeviceSensorV2/XnSensorProductionNode.h +++ b/Source/XnDeviceSensorV2/XnSensorProductionNode.h @@ -1,116 +1,116 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SENSOR_PRODUCTION_NODE_H__ -#define __XN_SENSOR_PRODUCTION_NODE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensor.h" -#include -#include "XnSensorClient.h" - -class XnMultiPropChangedHandler; // forward declaration - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorProductionNode : - virtual public xn::ModuleProductionNode, - virtual public xn::ModuleLockAwareInterface, - virtual public xn::ModuleExtendedSerializationInterface -{ -public: - XnSensorProductionNode(xn::Context& context, const XnChar* strInstanceName, XnDeviceBase* pSensor, const XnChar* strModuleName); - virtual ~XnSensorProductionNode(); - - // Production Node - XnBool IsCapabilitySupported(const XnChar* strCapabilityName); - XnStatus SetIntProperty(const XnChar* strName, XnUInt64 nValue); - XnStatus SetRealProperty(const XnChar* strName, XnDouble dValue); - XnStatus SetStringProperty(const XnChar* strName, const XnChar* strValue); - XnStatus SetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, const void* pBuffer); - XnStatus GetIntProperty(const XnChar* strName, XnUInt64& nValue) const; - XnStatus GetRealProperty(const XnChar* strName, XnDouble& dValue) const; - XnStatus GetStringProperty(const XnChar* strName, XnChar* csValue) const; - XnStatus GetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, void* pBuffer) const; - - // Lock Aware - xn::ModuleLockAwareInterface* GetLockAwareInterface() { return this; } - XnStatus SetLockState(XnBool bLocked); - XnBool GetLockState(); - XnStatus RegisterToLockChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); - void UnregisterFromLockChange(XnCallbackHandle hCallback); - - // Extended Serialization - xn::ModuleExtendedSerializationInterface* GetExtendedSerializationInterface() { return this; } - XnStatus NotifyExState(XnNodeNotifications* pNotifications, void* pCookie); - // TODO: Add RegisterExNotifications() which register to all props - void UnregisterExNotifications(); - - virtual XnStatus Init() { return XN_STATUS_OK; } - - inline XnDeviceBase* GetSensor() { return m_pSensor; } - inline const XnChar* GetModuleName() { return m_strModule; } - inline xn::Context& GetContext() { return m_Context; } - inline const XnChar* GetInstanceName() { return m_strInstanceName; } - -protected: - virtual void FilterProperties(XnActualPropertiesHash* pHash); - XnStatus RegisterToProps(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback, const XnChar** strNames, const XnChar* strModule = NULL); - void UnregisterFromProps(XnCallbackHandle hCallback); - - void OnModuleIntPropertyChanged(const XnChar* strModule, const XnChar* strProperty); - void OnModuleRealPropertyChanged(const XnChar* strModule, const XnChar* strProperty); - void OnModuleStringPropertyChanged(const XnChar* strModule, const XnChar* strProperty); - void OnModuleGeneralPropertyChanged(const XnChar* strModule, const XnChar* strProperty); - - static void XN_CALLBACK_TYPE IntPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); - static void XN_CALLBACK_TYPE RealPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); - static void XN_CALLBACK_TYPE StringPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); - static void XN_CALLBACK_TYPE GeneralPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); - - XN_DECLARE_DEFAULT_HASH(XnMultiPropChangedHandler*, XnMultiPropChangedHandler*, XnMultiPropChangedHandlerHash); - - xn::Context m_Context; - XnDeviceBase* m_pSensor; - XnChar m_strInstanceName[XN_MAX_NAME_LENGTH]; - XnChar m_strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnNodeNotifications* m_pNotifications; - void* m_pCookie; - - XnMultiPropChangedHandlerHash m_AllHandlers; - - XnCallbackHandle m_hIntProps; - XnCallbackHandle m_hRealProps; - XnCallbackHandle m_hStringProps; - XnCallbackHandle m_hGenProps; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SENSOR_PRODUCTION_NODE_H__ +#define __XN_SENSOR_PRODUCTION_NODE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensor.h" +#include +#include "XnSensorClient.h" + +class XnMultiPropChangedHandler; // forward declaration + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorProductionNode : + virtual public xn::ModuleProductionNode, + virtual public xn::ModuleLockAwareInterface, + virtual public xn::ModuleExtendedSerializationInterface +{ +public: + XnSensorProductionNode(xn::Context& context, const XnChar* strInstanceName, XnDeviceBase* pSensor, const XnChar* strModuleName); + virtual ~XnSensorProductionNode(); + + // Production Node + XnBool IsCapabilitySupported(const XnChar* strCapabilityName); + XnStatus SetIntProperty(const XnChar* strName, XnUInt64 nValue); + XnStatus SetRealProperty(const XnChar* strName, XnDouble dValue); + XnStatus SetStringProperty(const XnChar* strName, const XnChar* strValue); + XnStatus SetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, const void* pBuffer); + XnStatus GetIntProperty(const XnChar* strName, XnUInt64& nValue) const; + XnStatus GetRealProperty(const XnChar* strName, XnDouble& dValue) const; + XnStatus GetStringProperty(const XnChar* strName, XnChar* csValue, XnUInt32 nBufSize) const; + XnStatus GetGeneralProperty(const XnChar* strName, XnUInt32 nBufferSize, void* pBuffer) const; + + // Lock Aware + xn::ModuleLockAwareInterface* GetLockAwareInterface() { return this; } + XnStatus SetLockState(XnBool bLocked); + XnBool GetLockState(); + XnStatus RegisterToLockChange(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback); + void UnregisterFromLockChange(XnCallbackHandle hCallback); + + // Extended Serialization + xn::ModuleExtendedSerializationInterface* GetExtendedSerializationInterface() { return this; } + XnStatus NotifyExState(XnNodeNotifications* pNotifications, void* pCookie); + // TODO: Add RegisterExNotifications() which register to all props + void UnregisterExNotifications(); + + virtual XnStatus Init() { return XN_STATUS_OK; } + + inline XnDeviceBase* GetSensor() { return m_pSensor; } + inline const XnChar* GetModuleName() { return m_strModule; } + inline xn::Context& GetContext() { return m_Context; } + inline const XnChar* GetInstanceName() { return m_strInstanceName; } + +protected: + virtual void FilterProperties(XnActualPropertiesHash* pHash); + XnStatus RegisterToProps(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback, const XnChar** strNames, const XnChar* strModule = NULL); + void UnregisterFromProps(XnCallbackHandle hCallback); + + void OnModuleIntPropertyChanged(const XnChar* strModule, const XnChar* strProperty); + void OnModuleRealPropertyChanged(const XnChar* strModule, const XnChar* strProperty); + void OnModuleStringPropertyChanged(const XnChar* strModule, const XnChar* strProperty); + void OnModuleGeneralPropertyChanged(const XnChar* strModule, const XnChar* strProperty); + + static void XN_CALLBACK_TYPE IntPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); + static void XN_CALLBACK_TYPE RealPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); + static void XN_CALLBACK_TYPE StringPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); + static void XN_CALLBACK_TYPE GeneralPropertyChangedCallback(XnDeviceHandle pDeviceHandle, const XnChar* ModuleName, const XnChar* PropertyName, void* pCookie); + + XN_DECLARE_DEFAULT_HASH(XnMultiPropChangedHandler*, XnMultiPropChangedHandler*, XnMultiPropChangedHandlerHash); + + xn::Context m_Context; + XnDeviceBase* m_pSensor; + XnChar m_strInstanceName[XN_MAX_NAME_LENGTH]; + XnChar m_strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnNodeNotifications* m_pNotifications; + void* m_pCookie; + + XnMultiPropChangedHandlerHash m_AllHandlers; + + XnCallbackHandle m_hIntProps; + XnCallbackHandle m_hRealProps; + XnCallbackHandle m_hStringProps; + XnCallbackHandle m_hGenProps; +}; + #endif // __XN_SENSOR_PRODUCTION_NODE_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSensorServer.cpp b/Source/XnDeviceSensorV2/XnSensorServer.cpp index c9e5222..494cbab 100644 --- a/Source/XnDeviceSensorV2/XnSensorServer.cpp +++ b/Source/XnDeviceSensorV2/XnSensorServer.cpp @@ -1,1974 +1,345 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorServer.h" -#include "XnSensorClientServer.h" -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_SENSOR_DEFAULT_SERVER_WAIT_FOR_CLIENT_TIME 10000 -#define XN_SENSOR_SERVER_ACCEPT_CONNECTION_TIMEOUT 100 -#define XN_SENSOR_TERMINATE_READER_THREAD_TIMEOUT 5000 -#define XN_MASK_SENSOR_SERVER_COMM_DUMP "SensorServerComm" -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -typedef struct XnDeviceString -{ - XnChar str[XN_DEVICE_MAX_STRING_LENGTH]; -} XnDeviceString; - -typedef struct XnServerStream -{ - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nRefCount; - XnUInt32 nOpenRefCount; - XnStreamData* pStreamData; - XnBool bNewData; -} XnServerStream; - -XN_DECLARE_STRINGS_HASH(XnDeviceString, XnNamesHash); -XN_DECLARE_STRINGS_HASH(XnServerStream, XnServerStreamsHash); - -struct XnSensorServer::XnClient -{ - XnClient() - { - nID = 0; - hSocket = NULL; - hThread = NULL; - pStream = NULL; - pPrivateIncomingPacker = NULL; - pPrivateOutgoingPacker = NULL; - pServer = NULL; - pStreamDataSet = NULL; - XnDeviceString deviceModule = { XN_MODULE_NAME_DEVICE }; - clientToServerNames.Set(XN_MODULE_NAME_DEVICE, deviceModule); - serverToClientNames.Set(XN_MODULE_NAME_DEVICE, deviceModule); - bShouldRun = TRUE; - } - - ~XnClient() - { - XN_DELETE(pPrivateIncomingPacker); - XN_DELETE(pPrivateOutgoingPacker); - XN_DELETE(pStream); - if (hLock != NULL) - { - xnOSCloseCriticalSection(&hLock); - hLock = NULL; - } - if (pStreamDataSet != NULL) - { - XnStreamDataSetDestroy(&pStreamDataSet); - } - if (hSocket != NULL) - { - xnOSCloseSocket(hSocket); - } - } - - const XnChar* ToServerModule(const XnChar* strClientModule) - { - XnNamesHash::Iterator it = clientToServerNames.end(); - if (XN_STATUS_OK != clientToServerNames.Find(strClientModule, it)) - { - return NULL; - } - - return it.Value().str; - } - - const XnChar* FromServerModule(const XnChar* strServerModule) - { - XnNamesHash::Iterator it = serverToClientNames.end(); - if (XN_STATUS_OK != serverToClientNames.Find(strServerModule, it)) - { - return NULL; - } - - return it.Value().str; - } - - XnBool IsStreamOpen(const XnChar* strServerStream) - { - XnNamesHash::Iterator it = serverToClientNames.end(); - return (XN_STATUS_OK == openStreams.Find(strServerStream, it)); - } - - XnUInt32 nID; - XN_SOCKET_HANDLE hSocket; - XN_THREAD_HANDLE hThread; - XN_CRITICAL_SECTION_HANDLE hLock; - XnIONetworkStream* pStream; - XnDataPacker* pPrivateIncomingPacker; - XnDataPacker* pPrivateOutgoingPacker; - XnSensorServer* pServer; - XnStreamDataSet* pStreamDataSet; - XnNamesHash clientToServerNames; - XnNamesHash serverToClientNames; - volatile XnBool bShouldRun; - XnNamesHash openStreams; -}; - -#define XN_SENSOR_SERVER_LOCK_BLOCK XnAutoCSLocker __locker(m_hSensorLock); -#define XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK XnAutoCSLocker __locker(pClient->hLock); - -//--------------------------------------------------------------------------- -// XnSensorServer class -//--------------------------------------------------------------------------- -XnSensorServer::XnSensorServer() : - m_bSensorOpen(FALSE), - m_hListenSocket(NULL), - m_hReaderThread(NULL), - m_hNewDataEvent(NULL), - m_hServerRunningEvent(NULL), - m_hServerRunningMutex(NULL), - m_hSensorLock(NULL), - m_hBroadcastingLock(NULL), - m_hClientsCriticalSection(NULL), - m_nLastClientID(0), - m_pServerStreams(NULL), - m_noClientTimeout(XN_MODULE_PROPERTY_SERVER_NO_CLIENTS_TIMEOUT, XN_SENSOR_DEFAULT_SERVER_WAIT_FOR_CLIENT_TIME), - m_startNewLog(XN_MODULE_PROPERTY_SERVER_START_NEW_LOG_FILE), - m_nErrorState(XN_STATUS_OK) -{ - m_noClientTimeout.UpdateSetCallbackToDefault(); - m_startNewLog.UpdateSetCallback(StartNewLogCallback, this); - - m_serverDump = XN_DUMP_CLOSED; - xnDumpInit(&m_serverDump, XN_MASK_SENSOR_SERVER_COMM_DUMP, "TS,Type,Size,Client\n", "%s.csv", XN_MASK_SENSOR_SERVER_COMM_DUMP); -} - -XnSensorServer::~XnSensorServer() -{ - ShutdownServer(); -} - -XnStatus XnSensorServer::Run(const XnChar* strConfigFile) -{ - //Initialize server - XnStatus nRetVal = InitServer(strConfigFile); - - if (nRetVal == XN_STATUS_OK) - { - //Initialization succeeded - run main loop - nRetVal = ServerMainLoop(); - } - - //Shutdown the server - ShutdownServer(); - - return nRetVal; -} - -XnBool XnSensorServer::IsServerRunning() -{ - if (m_hServerRunningEvent == NULL) - { - return FALSE; - } - - //Poll the Server Running event - return xnOSIsEventSet(m_hServerRunningEvent); -} - -XnStatus XnSensorServer::InitServer(const XnChar* strConfigFile) -{ - XnStatus nRetVal = XN_STATUS_OK; - nRetVal = xnOSCreateNamedMutex(&m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_NAME); - XN_IS_STATUS_OK(nRetVal); - - XnAutoMutexLocker serverRunningLock(m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); - nRetVal = serverRunningLock.GetStatus(); - if (nRetVal != XN_STATUS_OK) - { - //This could mean there's another server/client that's frozen and they're jamming the mutex... - xnLogError(XN_MASK_SENSOR_SERVER, "Failed to lock server mutex: %s - exiting.", xnGetStatusString(nRetVal)); - XN_ASSERT(FALSE); - return XN_STATUS_OS_MUTEX_TIMEOUT; - } - - //From now on we're protected by m_hServerRunningMutex until we return from this function - - /*Create the Server Running event. - This is created as a manual-reset event, because only the server resets it when it's shutting down. */ - nRetVal = xnOSOpenNamedEvent(&m_hServerRunningEvent, XN_SENSOR_SERVER_RUNNING_EVENT_NAME); - if (nRetVal != XN_STATUS_OK) - { - nRetVal = xnOSCreateNamedEvent(&m_hServerRunningEvent, XN_SENSOR_SERVER_RUNNING_EVENT_NAME, TRUE); - XN_IS_STATUS_OK(nRetVal); - } - - if (IsServerRunning()) - { - //Another server is already running. - xnLogInfo(XN_MASK_SENSOR_SERVER, "Detected another server running - exiting."); - xnOSCloseEvent(&m_hServerRunningEvent); - m_hServerRunningEvent = NULL; - return XN_STATUS_DEVICE_SERVER_ALREADY_RUNNING; - } - - nRetVal = m_sensor.SetGlobalConfigFile(strConfigFile); - XN_IS_STATUS_OK(nRetVal); - - // read default timeout from file - nRetVal = m_noClientTimeout.ReadValueFromFile(strConfigFile, XN_CONFIG_FILE_SERVER_SECTION); - XN_IS_STATUS_OK(nRetVal); - - // init network - nRetVal = xnOSInitNetwork(); - XN_IS_STATUS_OK(nRetVal); - - // create locks - nRetVal = xnOSCreateCriticalSection(&m_hSensorLock); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateCriticalSection(&m_hBroadcastingLock); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = xnOSCreateCriticalSection(&m_hClientsCriticalSection); - XN_IS_STATUS_OK(nRetVal); - - // create the listen socket - nRetVal = xnOSCreateSocket(XN_OS_TCP_SOCKET, XN_SENSOR_SERVER_IP_ADDRESS, XN_SENSOR_SERVER_PORT, &m_hListenSocket); - XN_IS_STATUS_OK(nRetVal); - - // bind it - nRetVal = xnOSBindSocket(m_hListenSocket); - XN_IS_STATUS_OK(nRetVal); - - // register to events - nRetVal = m_sensor.OnStreamCollectionChangedEvent().Register(StreamCollectionChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_sensor.OnNewStreamDataEvent().Register(NewStreamDataCallback, this); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_NEW(m_pServerStreams, XnServerStreamsHash); - - nRetVal = xnOSCreateEvent(&m_hNewDataEvent, FALSE); - XN_IS_STATUS_OK(nRetVal); - - // start listening - nRetVal = xnOSListenSocket(m_hListenSocket); - XN_IS_STATUS_OK(nRetVal); - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Server is now listening"); - - /*Set the event to signal that the server is ready for requests. We do this AFTER we start listening so - the clients can wait on the event and then connect to the server socket. */ - nRetVal = xnOSSetEvent(m_hServerRunningEvent); - XN_IS_STATUS_OK(nRetVal); - - // start reader thread - nRetVal = xnOSCreateThread(ReaderThread, this, &m_hReaderThread); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OpenSensor(const XnChar* strConnectionString) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnDeviceConfig config; - config.DeviceMode = XN_DEVICE_MODE_READ; - config.cpConnectionString = strConnectionString; - config.pInitialValues = NULL; - config.SharingMode = XN_DEVICE_SHARED; - - nRetVal = m_sensor.Init(&config); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_ADD_PROPERTIES(m_sensor.DeviceModule(), - &m_startNewLog, &m_noClientTimeout); - - // configure from global file - nRetVal = m_sensor.ConfigureModuleFromGlobalFile(XN_MODULE_NAME_DEVICE, XN_CONFIG_FILE_SERVER_SECTION); - XN_IS_STATUS_OK(nRetVal); - - // register to all properties - XN_PROPERTY_SET_CREATE_ON_STACK(props); - nRetVal = m_sensor.DeviceModule()->GetAllProperties(&props); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = RegisterToProps(&props); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::ServerMainLoop() -{ - XnStatus nRetVal = XN_STATUS_OK; - XnUInt64 nNow = 0; - XnUInt64 nLastClientRemovedTimestamp = 0; - XnUInt64 nTimeSinceNoClients = 0; - XnBool bQuit = FALSE; - XN_SOCKET_HANDLE hClientSocket = NULL; - XnBool bNoClients = FALSE; - - xnOSGetTimeStamp(&nLastClientRemovedTimestamp); - - while (!bQuit) - { - nRetVal = xnOSAcceptSocket(m_hListenSocket, &hClientSocket, XN_SENSOR_SERVER_ACCEPT_CONNECTION_TIMEOUT); - if (nRetVal == XN_STATUS_OK) - { - xnLogInfo(XN_MASK_SENSOR_SERVER, "New client trying to connect..."); - - //TODO: Check if we don't have too many clients - nRetVal = AddClient(hClientSocket); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to add new client: %s", xnGetStatusString(nRetVal)); - xnOSCloseSocket(hClientSocket); - //Still in loop - } - } - else // no client trying to connect, do some clean up work - { - if (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT) - { - //Any other error beside timeout is not expected, but we treat it the same. - xnLogWarning(XN_MASK_SENSOR_SERVER, "failed to accept connection: %s", xnGetStatusString(nRetVal)); - } - - // remove all non-active clients - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - - if (!m_clients.IsEmpty()) - { - // create a list of all clients to be removed - XnClientsList toRemove; - for (XnClientsList::Iterator it = m_clients.begin(); it != m_clients.end(); ++it) - { - XnClient* pClient = *it; - if (!pClient->bShouldRun) - { - toRemove.AddLast(pClient); - } - } - - // now actually remove them - for (XnClientsList::Iterator it = toRemove.begin(); it != toRemove.end(); ++it) - { - XnClient* pClient = *it; - RemoveClient(pClient); - } - - // check if there are any clients left - if (m_clients.IsEmpty()) - { - xnOSGetTimeStamp(&nLastClientRemovedTimestamp); - - // do some clean-up (so that next client will behave as if it started the server) - ReturnToDefaults(); - } - } - - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - - // if too much time has passed and no client has connected, shut down - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - bNoClients = m_clients.IsEmpty(); - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - - xnOSGetTimeStamp(&nNow); - - nTimeSinceNoClients = (nNow - nLastClientRemovedTimestamp); - if (bNoClients && (nTimeSinceNoClients >= m_noClientTimeout.GetValue())) - { - xnLogInfo(XN_MASK_SENSOR_SERVER, "No client connection for %u ms. Shutting down...", m_noClientTimeout.GetValue()); - bQuit = TRUE; - } - } - } - - return XN_STATUS_OK; -} - -void XnSensorServer::ShutdownServer() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnAutoMutexLocker serverRunningLock(m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); - nRetVal = serverRunningLock.GetStatus(); - if (nRetVal != XN_STATUS_OK) - { - //This could mean there's another server/client that's frozen and they're jamming the mutex... - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to lock server mutex: %s - proceeding with shutdown.", xnGetStatusString(nRetVal)); - XN_ASSERT(FALSE); - } - - if (m_hServerRunningEvent != NULL) - { - nRetVal = xnOSResetEvent(m_hServerRunningEvent); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to reset sensor server event: %s - proceeding with shutdown.", xnGetStatusString(nRetVal)); - XN_ASSERT(FALSE); - } - - xnOSCloseEvent(&m_hServerRunningEvent); - m_hServerRunningEvent = NULL; - } - - nRetVal = m_sensor.Destroy(); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to destroy sensor: %s", xnGetStatusString(nRetVal)); - XN_ASSERT(FALSE); - } - - XN_DELETE(m_pServerStreams); - m_pServerStreams = NULL; - - for (XnPropertySetData::Iterator it = m_allStreamsProps.begin(); it != m_allStreamsProps.end(); ++it) - { - XN_DELETE(it.Value()); - } - m_allStreamsProps.Clear(); - - XN_ASSERT(m_clients.IsEmpty()); - - if (m_hNewDataEvent != NULL) - { - xnOSCloseEvent(&m_hNewDataEvent); - m_hNewDataEvent = NULL; - } - - if (m_hReaderThread != NULL) - { - xnOSWaitAndTerminateThread(&m_hReaderThread, XN_SENSOR_TERMINATE_READER_THREAD_TIMEOUT); - m_hReaderThread = NULL; - } - - if (m_hListenSocket != NULL) - { - xnOSCloseSocket(m_hListenSocket); - m_hListenSocket = NULL; - } - - if (m_hClientsCriticalSection != NULL) - { - xnOSCloseCriticalSection(&m_hClientsCriticalSection); - m_hClientsCriticalSection = NULL; - } - - if (m_hBroadcastingLock != NULL) - { - xnOSCloseCriticalSection(&m_hBroadcastingLock); - m_hBroadcastingLock = NULL; - } - - if (m_hSensorLock != NULL) - { - xnOSCloseCriticalSection(&m_hSensorLock); - m_hSensorLock = NULL; - } -} - -XnStatus XnSensorServer::RegisterToProps(XnPropertySet* pProps) -{ - XnStatus nRetVal = XN_STATUS_OK; - - for (XnPropertySetData::Iterator itMod = pProps->pData->begin(); itMod != pProps->pData->end(); ++itMod) - { - XnActualPropertiesHash* pHash = itMod.Value(); - - XnDeviceModule* pModule; - nRetVal = m_sensor.FindModule(itMod.Key(), &pModule); - XN_IS_STATUS_OK(nRetVal); - - for (XnActualPropertiesHash::Iterator itProp = pHash->begin(); itProp != pHash->end(); ++itProp) - { - XnProperty* pProp; - nRetVal = pModule->GetProperty(itProp.Key(), &pProp); - XN_IS_STATUS_OK(nRetVal); - - // no need to keep the handle. We only want to unregister when the stream is destroyed, and then - // it happens anyway. - nRetVal = pProp->OnChangeEvent().Register(PropertyChangedCallback, this); - XN_IS_STATUS_OK(nRetVal); - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OnNewServerEvent(const XnUChar* pData, XnUInt32 nDataSize, XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = pClient->pStream->WriteData(pData, nDataSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnSensorServer::DumpMessage(const XnChar* strType, XnUInt32 nSize /* = 0 */, XnUInt32 nClientID /* = 0 */, const XnChar* strComment /* = "" */ ) -{ - XnUInt64 nNow; - xnOSGetHighResTimeStamp(&nNow); - - xnDumpWriteString(m_serverDump, "%llu,%s,%d,%d,%s\n", nNow, strType, nSize, nClientID, strComment); -} - -XnStatus XnSensorServer::OnStreamAdded(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // get all props - XN_PROPERTY_SET_CREATE_ON_STACK(props); - nRetVal = m_sensor.GetAllProperties(&props, FALSE, StreamName); - XN_IS_STATUS_OK(nRetVal); - - // register to all props - nRetVal = RegisterToProps(&props); - XN_IS_STATUS_OK(nRetVal); - - XnActualPropertiesHash* pStreamProps = props.pData->begin().Value(); - - // take type - XnProperty* pProp = NULL; - nRetVal = pStreamProps->Get(XN_STREAM_PROPERTY_TYPE, pProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualStringProperty* pTypeProp = (XnActualStringProperty*)pProp; - - nRetVal = XnPropertySetDataDetachModule(props.pData, StreamName, &pStreamProps); - XN_IS_STATUS_OK(nRetVal); - - // add it to property list - nRetVal = XnPropertySetDataAttachModule(&m_allStreamsProps, StreamName, pStreamProps); - XN_IS_STATUS_OK(nRetVal); - - // create stream data - XnServerStream serverStream; - xnOSMemSet(&serverStream, 0, sizeof(serverStream)); - strcpy(serverStream.strType, StreamName); - nRetVal = m_sensor.CreateStreamData(StreamName, &serverStream.pStreamData); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pServerStreams->Set(StreamName, serverStream); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OnStreamRemoved(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // no need to unregister from its props - they do not exist anymore. - - // remove stream data - XnServerStream* pServerStream; - nRetVal = m_pServerStreams->Get(StreamName, pServerStream); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_sensor.DestroyStreamData(&pServerStream->pStreamData); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_pServerStreams->Remove(StreamName); - XN_IS_STATUS_OK(nRetVal); - - // remove from our list - XnActualPropertiesHash* pStreamProps = NULL; - nRetVal = XnPropertySetDataDetachModule(&m_allStreamsProps, StreamName, &pStreamProps); - XN_IS_STATUS_OK(nRetVal); - - XN_DELETE(pStreamProps); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType) -{ - XnStatus nRetVal = XN_STATUS_OK; - - switch (EventType) - { - case XN_DEVICE_STREAM_ADDED: - { - nRetVal = OnStreamAdded(StreamName); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_DEVICE_STREAM_DELETED: - { - nRetVal = OnStreamRemoved(StreamName); - XN_IS_STATUS_OK(nRetVal); - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "unknown event: %d", EventType); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OnPropertyChanged(const XnProperty* pProp) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUInt64 nValue = 0; - XnDouble dValue = 0; - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - XnGeneralBuffer gbValue = {NULL, 0}; - XnBool bPassPropToClients = TRUE; - - switch (pProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XnIntProperty* pIntProp = (XnIntProperty*)pProp; - nRetVal = pIntProp->GetValue(&nValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = OnIntPropertyChangedInternally(pProp->GetName(), nValue, bPassPropToClients); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XnRealProperty* pRealProp = (XnRealProperty*)pProp; - nRetVal = pRealProp->GetValue(&dValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = OnRealPropertyChangedInternally(pProp->GetName(), dValue, bPassPropToClients); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XnStringProperty* pStringProp = (XnStringProperty*)pProp; - nRetVal = pStringProp->GetValue(strValue); - XN_IS_STATUS_OK(nRetVal); - nRetVal = OnStringPropertyChangedInternally(pProp->GetName(), strValue, bPassPropToClients); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XnGeneralProperty* pGenProp = (XnGeneralProperty*)pProp; - - // find its size from properties map - XnActualPropertiesHash* pModule; - nRetVal = m_allStreamsProps.Get(pProp->GetModule(), pModule); - XN_IS_STATUS_OK(nRetVal); - - XnProperty* pActualProp; - nRetVal = pModule->Get(pProp->GetName(), pActualProp); - XN_IS_STATUS_OK(nRetVal); - - XnActualGeneralProperty* pActualGenProp = (XnActualGeneralProperty*)pActualProp; - - // allocate - nRetVal = XnGeneralBufferAlloc(&gbValue, pActualGenProp->GetValue().nDataSize); - XN_IS_STATUS_OK(nRetVal); - - // take value - nRetVal = pGenProp->GetValue(gbValue); - if (nRetVal != XN_STATUS_OK) - { - XnGeneralBufferFree(&gbValue); - return nRetVal; - } - - nRetVal = OnGeneralPropertyChangedInternally(pProp->GetName(), gbValue, bPassPropToClients); - if (nRetVal != XN_STATUS_OK) - { - XnGeneralBufferFree(&gbValue); - return nRetVal; - } - - break; - } - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Unknown property type: %d", pProp->GetType()); - } - - if (bPassPropToClients) - { - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - for (XnClientsList::Iterator it = m_clients.begin(); it != m_clients.end(); ++it) - { - XnClient* pClient = *it; - const XnChar* strModule = pClient->FromServerModule(pProp->GetModule()); - if (strModule == NULL) - { - continue; - } - - // send message - DumpMessage("PropChange", 0, pClient->nID, pProp->GetName()); - switch (pProp->GetType()) - { - case XN_PROPERTY_TYPE_INTEGER: - { - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteProperty(strModule, pProp->GetName(), nValue); - break; - } - case XN_PROPERTY_TYPE_REAL: - { - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteProperty(strModule, pProp->GetName(), dValue); - break; - } - case XN_PROPERTY_TYPE_STRING: - { - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteProperty(strModule, pProp->GetName(), strValue); - break; - } - case XN_PROPERTY_TYPE_GENERAL: - { - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteProperty(strModule, pProp->GetName(), gbValue); - break; - } - } - - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - XnGeneralBufferFree(&gbValue); - return nRetVal; - } - } // clients loop - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - } - - // free allocated buffer - XnGeneralBufferFree(&gbValue); - return XN_STATUS_OK; -} - -XnStatus XnSensorServer::ReadStreams() -{ - XnStatus nRetVal = XN_STATUS_OK; - - while (IsServerRunning()) - { - nRetVal = xnOSWaitEvent(m_hNewDataEvent, XN_NODE_WAIT_FOR_DATA_TIMEOUT); - if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) - { - continue; - } - - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Got error waiting for new data event: %s", xnGetStatusString(nRetVal)); - } - - typedef struct - { - XnUInt64 nTimestamp; - XnUInt32 nFrameID; - XnChar strName[XN_MAX_NAME_LENGTH]; - } NewStreamData; - - NewStreamData aNewStreamData[5]; - XnUInt32 nCount = 0; - - // read streams with lock - { - XN_SENSOR_SERVER_LOCK_BLOCK; - for (XnServerStreamsHash::Iterator it = m_pServerStreams->begin(); it != m_pServerStreams->end(); ++it) - { - XnServerStream& stream = it.Value(); - - if (stream.bNewData) - { - // ignore audio (it is read by every client) - if (strcmp(stream.strType, XN_STREAM_NAME_AUDIO) != 0) - { - // read this data - nRetVal = m_sensor.ReadStream(stream.pStreamData); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed reading from stream %s (though event was raised): %s", stream.strType, xnGetStatusString(nRetVal)); - stream.bNewData = FALSE; - continue; - } - } - - stream.bNewData = FALSE; - - aNewStreamData[nCount].nTimestamp = stream.pStreamData->nTimestamp; - aNewStreamData[nCount].nFrameID = stream.pStreamData->nFrameID; - strcpy(aNewStreamData[nCount].strName, stream.strType); - nCount++; - } - } // streams loop - } // lock - - // now send notifications (outside of server lock) - for (XnUInt32 i = 0; i < nCount; ++i) - { - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - for (XnClientsList::Iterator it = m_clients.begin(); it != m_clients.end(); ++it) - { - XnClient* pClient = *it; - - // check if client has stream open - if (!pClient->IsStreamOpen(aNewStreamData[i].strName)) - { - continue; - } - - // notify about the new data - const XnChar* strStreamName = pClient->FromServerModule(aNewStreamData[i].strName); - if (strStreamName != NULL) - { - XnSensorServerNewStreamData message; - xnOSMemSet(&message, 0, sizeof(message)); - message.nTimestamp = aNewStreamData[i].nTimestamp; - message.nFrameID = aNewStreamData[i].nFrameID; - strcpy(message.strStreamName, strStreamName); - DumpMessage("NewData", sizeof(XnSensorServerNewStreamData), 0, strStreamName); - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteCustomData(XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA, &message, sizeof(XnSensorServerNewStreamData)); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed sending new data event to client %d", pClient->nID); - } //if (nRetVal != XN_STATUS_OK) - } //if (strStreamName != NULL) - } //for (clients) - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - } - - } //while (m_bShouldRun) - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::OnNewStreamData(const XnChar* StreamName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnServerStream* pStream; - nRetVal = m_pServerStreams->Get(StreamName, pStream); - XN_IS_STATUS_OK(nRetVal); - - pStream->bNewData = TRUE; - - nRetVal = xnOSSetEvent(m_hNewDataEvent); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::SendInitialState(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XN_PROPERTY_SET_CREATE_ON_STACK(props); - - // get it - nRetVal = m_sensor.GetAllProperties(&props, TRUE); - XN_IS_STATUS_OK(nRetVal); - - // and send it - DumpMessage("InitialState", 0, pClient->nID); - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WritePropertySet(&props); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::AddClient(XN_SOCKET_HANDLE hClientSocket) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // create new client - XnClient* pClient; - XN_VALIDATE_NEW(pClient, XnClient); - pClient->hSocket = hClientSocket; - pClient->pServer = this; - pClient->pStream = XN_NEW(XnIONetworkStream, pClient->hSocket); - pClient->pPrivateIncomingPacker = XN_NEW(XnDataPacker, pClient->pStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE); - pClient->pPrivateOutgoingPacker = XN_NEW(XnDataPacker, pClient->pStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE); - - if (pClient->pStream == NULL || pClient->pPrivateIncomingPacker == NULL || pClient->pPrivateOutgoingPacker == NULL) - { - XN_DELETE(pClient); - return (XN_STATUS_ALLOC_FAILED); - } - - nRetVal = XnStreamDataSetCreate(&pClient->pStreamDataSet); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pClient); - return (XN_STATUS_ALLOC_FAILED); - } - - nRetVal = xnOSCreateCriticalSection(&pClient->hLock); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pClient); - return (nRetVal); - } - - nRetVal = pClient->pPrivateIncomingPacker->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pClient); - return (nRetVal); - } - - nRetVal = pClient->pPrivateOutgoingPacker->Init(); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pClient); - return (nRetVal); - } - - // lock the device (so that configuration wouldn't change before we register to it all) - { - XN_SENSOR_SERVER_LOCK_BLOCK; - - m_nLastClientID++; - pClient->nID = m_nLastClientID; - - // create thread - nRetVal = xnOSCreateThread(ClientThread, pClient, &pClient->hThread); - if (nRetVal != XN_STATUS_OK) - { - xnOSLeaveCriticalSection(&m_hSensorLock); - XN_DELETE(pClient); - return (nRetVal); - } - - // add it to clients list - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - m_clients.AddLast(pClient); - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - - } // lock end - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::RemoveClientStream(XnClient* pClient, const XnChar* strName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - const XnChar* strServerName = pClient->ToServerModule(strName); - if (strServerName == NULL) - { - return XN_STATUS_NO_MATCH; - } - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u is releasing stream %s", pClient->nID, strServerName); - - // first of all, if client had a buffer of this stream, release it - XnStreamData* pStreamData = NULL; - nRetVal = XnStreamDataSetGet(pClient->pStreamDataSet, strServerName, &pStreamData); - if (nRetVal == XN_STATUS_OK) - { - XnSharedMemoryBufferPool* pBufferPool = NULL; - nRetVal = m_sensor.GetSharedBufferPool(strServerName, &pBufferPool); - XN_IS_STATUS_OK(nRetVal); - - if (pStreamData->pInternal->pLockedBuffer != NULL) - { - pBufferPool->DecRef(pStreamData->pInternal->pLockedBuffer); - } - - // free data - XnStreamDataSetRemove(pClient->pStreamDataSet, pStreamData); - XnStreamDataDestroy(&pStreamData); - } - - // and dec ref it - XnServerStream* pStream; - nRetVal = m_pServerStreams->Get(strServerName, pStream); - if (nRetVal == XN_STATUS_OK) - { - XN_SENSOR_SERVER_LOCK_BLOCK; - --pStream->nRefCount; - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s now has %u clients", strServerName, pStream->nRefCount); - - if (pStream->nRefCount == 0) - { - m_sensor.CloseStream(strServerName); - m_sensor.DestroyStream(strServerName); - - // the rest will be done in the OnStreamRemoved event handler... - } - } - - // now remove it from client - pClient->serverToClientNames.Remove(strServerName); - pClient->clientToServerNames.Remove(strName); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::RemoveClient(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Removing client %u...", pClient->nID); - - pClient->bShouldRun = FALSE; - - // dec ref of every stream - while (!pClient->clientToServerNames.IsEmpty()) - { - RemoveClientStream(pClient, pClient->clientToServerNames.begin().Key()); - } - - xnOSEnterCriticalSection(&m_hClientsCriticalSection); - XnClientsList::ConstIterator it = m_clients.Find(pClient); - m_clients.Remove(it); - xnOSLeaveCriticalSection(&m_hClientsCriticalSection); - - xnOSWaitAndTerminateThread(&pClient->hThread, 3000); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u removed", pClient->nID); - XN_DELETE(pClient); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::ReturnToDefaults() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // This is a bit ugly, but we need to manually set back to default DEVICE properties - // (we know there aren't any streams and clients, but the Device module always remains) - nRetVal = m_sensor.SetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)FALSE); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_sensor.ConfigureModuleFromGlobalFile(XN_MODULE_NAME_DEVICE); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::SendReply(XnClient* pClient, XnSensorServerCustomMessages Type, XnStatus nRC, XnUInt32 nDataSize /* = 0 */, void* pAdditionalData /* = NULL */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnUChar message[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; - XnSensorClientServerReply* pReply = (XnSensorClientServerReply*)message; - pReply->nRetVal = nRC; - pReply->Type = Type; - pReply->nDataSize = nDataSize; - xnOSMemCopy(pReply->pData, pAdditionalData, nDataSize); - XnUChar* pEnd = pReply->pData + nDataSize; - - DumpMessage("Reply", nDataSize, pClient->nID); - - // lock this so that messages don't mix up - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - - nRetVal = pClient->pPrivateOutgoingPacker->WriteCustomData(Type, message, pEnd - message); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleOpenSensor(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strConnectionString[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, strConnectionString, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to open sensor %s", pClient->nID, strConnectionString); - - // make sure sensor is open - { - XN_SENSOR_SERVER_LOCK_BLOCK; - if (!m_bSensorOpen) - { - nRetVal = OpenSensor(strConnectionString); - m_bSensorOpen = (nRetVal == XN_STATUS_OK); - } - - if (nRetVal == XN_STATUS_OK) - { - // sensor is open. send client its initial state - nRetVal = SendInitialState(pClient); - } - } - - // if an error occurred, send it to the client - if (nRetVal != XN_STATUS_OK) - { - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleSetIntProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt64 nValue; - nRetVal = pClient->pPrivateIncomingPacker->ReadProperty(strModule, strProp, &nValue); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", pClient->nID, strModule, strProp); - - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.SetProperty(pClient->ToServerModule(strModule), strProp, nValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleSetRealProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnDouble dValue; - nRetVal = pClient->pPrivateIncomingPacker->ReadProperty(strModule, strProp, &dValue); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", pClient->nID, strModule, strProp); - - // set - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.SetProperty(pClient->ToServerModule(strModule), strProp, dValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleSetStringProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = pClient->pPrivateIncomingPacker->ReadProperty(strModule, strProp, strValue); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", pClient->nID, strModule, strProp); - - // set - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.SetProperty(pClient->ToServerModule(strModule), strProp, strValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleSetGeneralProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - XnGeneralBuffer gbValue; - nRetVal = pClient->pPrivateIncomingPacker->ReadProperty(strModule, strProp, &gbValue); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", pClient->nID, strModule, strProp); - - // set - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.SetProperty(pClient->ToServerModule(strModule), strProp, gbValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleGetIntProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnSensorServerMessageGetPropertyRequest request; - XnUInt32 nDataSize = sizeof(request); - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, &request, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - if (nDataSize != sizeof(request)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); - } - - XnUInt64 nValue; - { - XN_SENSOR_SERVER_LOCK_BLOCK; - - nRetVal = m_sensor.GetProperty(pClient->ToServerModule(request.strModuleName), request.strPropertyName, &nValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, nRetVal, sizeof(nValue), &nValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleGetRealProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnSensorServerMessageGetPropertyRequest request; - XnUInt32 nDataSize = sizeof(request); - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, &request, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - if (nDataSize != sizeof(request)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); - } - - XnDouble dValue; - { - XN_SENSOR_SERVER_LOCK_BLOCK; - - nRetVal = m_sensor.GetProperty(pClient->ToServerModule(request.strModuleName), request.strPropertyName, &dValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, nRetVal, sizeof(dValue), &dValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleGetStringProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnSensorServerMessageGetPropertyRequest request; - XnUInt32 nDataSize = sizeof(request); - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, &request, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - if (nDataSize != sizeof(request)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); - } - - XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; - { - XN_SENSOR_SERVER_LOCK_BLOCK; - - nRetVal = m_sensor.GetProperty(pClient->ToServerModule(request.strModuleName), request.strPropertyName, strValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, nRetVal, sizeof(strValue), strValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleGetGeneralProperty(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnUChar bufValue[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; - XnSensorServerMessageGetPropertyRequest* pRequest = (XnSensorServerMessageGetPropertyRequest*)bufValue; - XnUChar* pData = bufValue + sizeof(XnSensorServerMessageGetPropertyRequest); - XnUInt32 nDataSize = XN_SENSOR_SERVER_MAX_REPLY_SIZE; - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, bufValue, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - if (nDataSize < sizeof(XnSensorServerMessageGetPropertyRequest)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); - } - - XnGeneralBuffer gbValue = XnGeneralBufferPack(pData, pRequest->nSize); - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.GetProperty(pClient->ToServerModule(pRequest->strModuleName), pRequest->strPropertyName, gbValue); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, nRetVal, pRequest->nSize, pData); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleConfigFromINIFile(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnSensorServerMessageIniFile message; - XnUInt32 nDataSize = sizeof(message); - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_INI_FILE, (XnUChar*)&message, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - if (nDataSize != sizeof(message)) - { - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); - } - - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.LoadConfigFromFile(message.strFileName, message.strSectionName); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleBatchConfig(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XN_PROPERTY_SET_CREATE_ON_STACK(props); - - nRetVal = pClient->pPrivateIncomingPacker->ReadPropertySet(&props); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested a batch config", pClient->nID); - - XN_PROPERTY_SET_CREATE_ON_STACK(serverProps); - for (XnPropertySetData::Iterator it = props.pData->begin(); it != props.pData->end(); ++it) - { - if (nRetVal == XN_STATUS_OK) - { - nRetVal = XnPropertySetCloneModule(&props, &serverProps, it.Key(), pClient->ToServerModule(it.Key())); - } - } - - if (nRetVal == XN_STATUS_OK) - { - XN_SENSOR_SERVER_LOCK_BLOCK; - nRetVal = m_sensor.BatchConfig(&serverProps); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleNewStream(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XN_PROPERTY_SET_CREATE_ON_STACK(props); - - XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = pClient->pPrivateIncomingPacker->ReadNewStream(strType, strName, &props); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to create stream '%s' (%s)", pClient->nID, strName, strType); - - XnPropertySet* pInitialValues = &props; - if (props.pData->begin() == props.pData->end()) - { - pInitialValues = NULL; - } - - // if a stream of this type already exists, take it instead - XnServerStream* pServerStream; - - XN_SENSOR_SERVER_LOCK_BLOCK; - - if (XN_STATUS_OK == m_pServerStreams->Get(strType, pServerStream)) - { - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s already exists.", strType); - // configure it - if (pInitialValues != NULL) - { - nRetVal = m_sensor.BatchConfig(pInitialValues); - } - } - else - { - // create the stream - nRetVal = m_sensor.CreateStream(strType, strType, pInitialValues); - - if (nRetVal == XN_STATUS_OK) - { - nRetVal = m_pServerStreams->Get(strType, pServerStream); - } - } - - // send client the new stream data - if (nRetVal == XN_STATUS_OK) - { - XN_PROPERTY_SET_CREATE_ON_STACK(streamProps); - XN_PROPERTY_SET_CREATE_ON_STACK(clientStreamProps); - - if (nRetVal == XN_STATUS_OK) - { - // take properties - nRetVal = m_sensor.GetAllProperties(&streamProps, FALSE, strType); - } - - if (nRetVal == XN_STATUS_OK) - { - // copy relevant ones - nRetVal = XnPropertySetCloneModule(&streamProps, &clientStreamProps, strType, strName); - } - - if (nRetVal == XN_STATUS_OK) - { - // now change the state property. It should be OFF, and not the real value (each client has - // its own stream state). - nRetVal = XnPropertySetRemoveProperty(&clientStreamProps, strName, XN_STREAM_PROPERTY_STATE); - } - - if (nRetVal == XN_STATUS_OK) - { - nRetVal = XnPropertySetAddIntProperty(&clientStreamProps, strName, XN_STREAM_PROPERTY_STATE, FALSE); - } - - if (nRetVal == XN_STATUS_OK) - { - DumpMessage("NewStream", 0, pClient->nID, strName); - { - XN_SENSOR_SERVER_CLIENT_LOCK_BLOCK; - nRetVal = pClient->pPrivateOutgoingPacker->WriteNewStream(strType, strName, &clientStreamProps); - } - } - } - - // add ref to it - if (nRetVal == XN_STATUS_OK) - { - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u adding ref to stream '%s'", pClient->nID, strType); - ++pServerStream->nRefCount; - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s now has %u clients.", strType, pServerStream->nRefCount); - } - - // now add it to client data - XnStreamData* pStreamData = NULL; - if (nRetVal == XN_STATUS_OK) - { - // add names mapping - XnDeviceString str; - strcpy(str.str, strType); - pClient->clientToServerNames.Set(strName, str); - strcpy(str.str, strName); - pClient->serverToClientNames.Set(strType, str); - - // create client stream data - nRetVal = m_sensor.CreateStreamData(strType, &pStreamData); - } - - if (nRetVal == XN_STATUS_OK) - { - // and add it to set - nRetVal = XnStreamDataSetAdd(pClient->pStreamDataSet, pStreamData); - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleRemoveStream(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; - nRetVal = pClient->pPrivateIncomingPacker->ReadStreamRemoved(strName); - XN_IS_STATUS_OK(nRetVal); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to close stream %s", pClient->nID, strName); - - nRetVal = RemoveClientStream(pClient, strName); - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleReadStream(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(XN_SENSOR_SERVER_MESSAGE_READ_STREAM, strStreamName, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - const XnChar* strServerName = pClient->ToServerModule(strStreamName); - - // take client stream data and server stream data - XnStreamData* pStreamData; - nRetVal = XnStreamDataSetGet(pClient->pStreamDataSet, strServerName, &pStreamData); - - XnServerStream* pServerStream = NULL; - - if (nRetVal == XN_STATUS_OK) - { - nRetVal = m_pServerStreams->Get(strServerName, pServerStream); - } - - XnSharedMemoryBufferPool* pBufferPool = NULL; - XnBuffer* pDecRef = NULL; - if (nRetVal == XN_STATUS_OK) - { - pDecRef = pStreamData->pInternal->pLockedBuffer; - nRetVal = m_sensor.GetSharedBufferPool(strServerName, &pBufferPool); - } - - if (nRetVal == XN_STATUS_OK) - { - // take server data for this stream, and add ref to it - XN_SENSOR_SERVER_LOCK_BLOCK; - pStreamData->nDataSize = pServerStream->pStreamData->nDataSize; - pStreamData->nFrameID = pServerStream->pStreamData->nFrameID; - pStreamData->nTimestamp = pServerStream->pStreamData->nTimestamp; - pStreamData->pData = pServerStream->pStreamData->pData; - pStreamData->pInternal->pLockedBuffer = pServerStream->pStreamData->pInternal->pLockedBuffer; - - if (pStreamData->pInternal->pLockedBuffer != NULL) - { - pBufferPool->AddRef(pStreamData->pInternal->pLockedBuffer); - } - - if (pDecRef != NULL) - { - pBufferPool->DecRef(pDecRef); - } - - XnSensorServerReadReply reply; - reply.nDataSize = pStreamData->nDataSize; - reply.nFrameID = pStreamData->nFrameID; - reply.nTimestamp = pStreamData->nTimestamp; - reply.nOffset = pBufferPool->GetBufferOffset(pStreamData->pInternal->pLockedBuffer); - - DumpMessage("Data", sizeof(reply), 0, strStreamName); - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_READ_STREAM, XN_STATUS_OK, sizeof(reply), &reply); - XN_IS_STATUS_OK(nRetVal); - } - else - { - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::HandleSetStreamState(XnClient* pClient, XnBool bRequestOpen) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // read it - XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; - XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; - XnUInt32 nType = bRequestOpen ? XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM : XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM; - nRetVal = pClient->pPrivateIncomingPacker->ReadCustomData(nType, strStreamName, &nDataSize); - XN_IS_STATUS_OK(nRetVal); - - const XnChar* strServerName = pClient->ToServerModule(strStreamName); - - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to %s stream %s", pClient->nID, bRequestOpen ? "open" : "close", strServerName); - - { - XN_SENSOR_SERVER_LOCK_BLOCK; - XnServerStream* pServerStream = NULL; - - if (nRetVal == XN_STATUS_OK) - { - nRetVal = m_pServerStreams->Get(strServerName, pServerStream); - } - - if (nRetVal == XN_STATUS_OK) - { - // check if this stream is currently open for this client (meaning, client - // receives its data) - XnBool bIsOpenForClient = FALSE; - XnNamesHash::Iterator it = pClient->openStreams.end(); - bIsOpenForClient = (pClient->openStreams.Find(strServerName, it) == XN_STATUS_OK); - - if (bRequestOpen && !bIsOpenForClient) - { - XnDeviceString dummy; - nRetVal = pClient->openStreams.Set(strServerName, dummy); - - if (nRetVal == XN_STATUS_OK) - { - pServerStream->nOpenRefCount++; - - if (pServerStream->nOpenRefCount == 1) // first one to open - { - // open it - nRetVal = m_sensor.OpenStream(strServerName); - } - - if (nRetVal != XN_STATUS_OK) - { - xnLogError(XN_MASK_SENSOR_SERVER, "Failed to open stream: %s", xnGetStatusString(nRetVal)); - XN_ASSERT(pServerStream->nOpenRefCount > 0); - --pServerStream->nOpenRefCount; - pClient->openStreams.Remove(strServerName); - } - else - { - xnLogInfo(XN_MASK_SENSOR_SERVER, "Stream %s is now open by %u clients.", strServerName, pServerStream->nOpenRefCount); - } - } - } - else if (!bRequestOpen && bIsOpenForClient) - { - pClient->openStreams.Remove(strServerName); - xnLogInfo(XN_MASK_SENSOR_SERVER, "Stream %s is now open by %u clients.", strServerName, pServerStream->nOpenRefCount); - --pServerStream->nOpenRefCount; - - if (pServerStream->nOpenRefCount == 0) - { - m_sensor.CloseStream(strServerName); - } - } - else - { - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client requested to %s stream %s, but this was already the state.", bRequestOpen ? "open" : "close", strServerName); - } - } - } - - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nRetVal); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - - -XnStatus XnSensorServer::HandleSingleRequest(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnPackedDataType nType; - nRetVal = pClient->pPrivateIncomingPacker->ReadNextObject(&nType); - XN_IS_STATUS_OK(nRetVal); - - XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; - XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; - - switch (nType) - { - case XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR: - { - nRetVal = HandleOpenSensor(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_INT_PROPERTY: - { - nRetVal = HandleSetIntProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_REAL_PROPERTY: - { - nRetVal = HandleSetRealProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_STRING_PROPERTY: - { - nRetVal = HandleSetStringProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_GENERAL_PROPERTY: - { - nRetVal = HandleSetGeneralProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY: - { - nRetVal = HandleGetIntProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY: - { - nRetVal = HandleGetRealProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY: - { - nRetVal = HandleGetStringProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY: - { - nRetVal = HandleGetGeneralProperty(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_INI_FILE: - { - nRetVal = HandleConfigFromINIFile(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_PROPERTY_SET: - { - nRetVal = HandleBatchConfig(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_NEW_STREAM: - { - nRetVal = HandleNewStream(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_PACKED_STREAM_REMOVED: - { - nRetVal = HandleRemoveStream(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_READ_STREAM: - { - nRetVal = HandleReadStream(pClient); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM: - { - nRetVal = HandleSetStreamState(pClient, TRUE); - XN_IS_STATUS_OK(nRetVal); - break; - } - case XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM: - { - nRetVal = HandleSetStreamState(pClient, FALSE); - XN_IS_STATUS_OK(nRetVal); - break; - } - - case XN_SENSOR_SERVER_MESSAGE_BYE: - { - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Received BYE from client %u", pClient->nID); - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_BYE, nRetVal, 0, NULL); - if (nRetVal != XN_STATUS_OK) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to send BYE reply to client %u: %s", pClient->nID, xnGetStatusString(nRetVal)); - } - pClient->bShouldRun = FALSE; //Signal the client to stop - - break; - } - - default: - xnLogWarning(XN_MASK_SENSOR_SERVER, "Unknown client request: %d", nType); - nRetVal = SendReply(pClient, XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, XN_STATUS_ERROR); - XN_IS_STATUS_OK(nRetVal); - - return XN_STATUS_ERROR; - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorServer::ServeClient(XnClient* pClient) -{ - XnStatus nRetVal = XN_STATUS_OK; - - while (IsServerRunning() && pClient->bShouldRun) - { - if (!pClient->pStream->IsConnected()) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Client %u socket was closed.", pClient->nID); - break; - } - - nRetVal = HandleSingleRequest(pClient); - if ((nRetVal != XN_STATUS_OK) && - (nRetVal != XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) && - (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT)) - { - xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed processing client request: %s", xnGetStatusString(nRetVal)); - } - } - - // We cannot RemoveClient from this thread (as part of it is to close the thread). Instead, signal that - // client has stopped, and let server main thread wait for exit. - pClient->bShouldRun = FALSE; - - return (XN_STATUS_OK); -} - -XN_THREAD_PROC XnSensorServer::ClientThread(XN_THREAD_PARAM pThreadParam) -{ - XnClient* pClient = (XnClient*)pThreadParam; - XnStatus nRetVal = pClient->pServer->ServeClient(pClient); - XN_THREAD_PROC_RETURN(nRetVal); -} - -XN_THREAD_PROC XnSensorServer::ReaderThread(XN_THREAD_PARAM pThreadParam) -{ - XnSensorServer* pThis = (XnSensorServer*)pThreadParam; - XnStatus nRetVal = pThis->ReadStreams(); - XN_THREAD_PROC_RETURN(nRetVal); -} - -void XnSensorServer::StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie) -{ - XnSensorServer* pThis = (XnSensorServer*)pCookie; - pThis->OnStreamCollectionChanged(StreamName, EventType); -} - -XnStatus XN_CALLBACK_TYPE XnSensorServer::PropertyChangedCallback(const XnProperty* pProp, void* pCookie) -{ - XnSensorServer* pThis = (XnSensorServer*)pCookie; - return pThis->OnPropertyChanged(pProp); -} - -void XN_CALLBACK_TYPE XnSensorServer::NewServerEventCallback(const XnUChar* pData, XnUInt32 nDataSize, void* pCookie) -{ - XnClient* pClient = (XnClient*)pCookie; - pClient->pServer->OnNewServerEvent(pData, nDataSize, pClient); -} - -void XN_CALLBACK_TYPE XnSensorServer::NewStreamDataCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, void* pCookie) -{ - XnSensorServer* pThis = (XnSensorServer*)pCookie; - pThis->OnNewStreamData(StreamName); -} - -XnStatus XN_CALLBACK_TYPE XnSensorServer::StartNewLogCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) -{ - xnLogVerbose(XN_MASK_SENSOR_SERVER, "Closing current log file..."); - return xnLogStartNewFile(); -} - -XnStatus XnSensorServer::OnIntPropertyChangedInternally(const XnChar* strPropName, XnUInt64 nValue, XnBool& bPassPropToClients) -{ - XnStatus nRetVal = XN_STATUS_OK; - bPassPropToClients = TRUE; - - if (strcmp(strPropName, XN_STREAM_PROPERTY_STATE) == 0) - { - // ignore STATE property (every client has its own value) - bPassPropToClients = FALSE; - } - else if (strcmp(strPropName, XN_MODULE_PROPERTY_ERROR_STATE) == 0) - { - XnStatus nOldErrorState = m_nErrorState; - m_nErrorState = (XnStatus)nValue; - switch (m_nErrorState) - { - case XN_STATUS_DEVICE_NOT_CONNECTED: - //TODO: Handle disconnection - break; - case XN_STATUS_OK: - if (nOldErrorState == XN_STATUS_DEVICE_NOT_CONNECTED) - { - //TODO: Handle re-connection - break; - } - } - } - - return XN_STATUS_OK; -} - -XnStatus XnSensorServer::OnRealPropertyChangedInternally(const XnChar* strPropName, XnDouble dValue, XnBool& bPassPropToClients) -{ - bPassPropToClients = TRUE; - return XN_STATUS_OK; -} - -XnStatus XnSensorServer::OnStringPropertyChangedInternally(const XnChar* strPropName, const XnChar* strValue, XnBool& bPassPropToClients) -{ - bPassPropToClients = TRUE; - return XN_STATUS_OK; -} - -XnStatus XnSensorServer::OnGeneralPropertyChangedInternally(const XnChar* strPropName, const XnGeneralBuffer &gbValue, XnBool& bPassPropToClients) -{ - bPassPropToClients = TRUE; - return XN_STATUS_OK; -} - -XN_DEVICE_API XnStatus XnSensorServerGetGlobalConfigFile(const XnChar* strConfigDir, XnChar* strConfigFile, XnUInt32 nBufSize) -{ - return XnSensor::ResolveGlobalConfigFileName(strConfigFile, nBufSize, strConfigDir); -} - -XN_DEVICE_API XnStatus XnSensorServerRun(const XnChar* strConfigFile) -{ - XnSensorServer server; - return server.Run(strConfigFile); -} - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorServer.h" +#include "XnSensorClientServer.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_SERVER_ACCEPT_CONNECTION_TIMEOUT 100 + +//--------------------------------------------------------------------------- +// XnSensorServer class +//--------------------------------------------------------------------------- +XnSensorServer::XnSensorServer(const XnChar* strConfigFile) : + m_hListenSocket(NULL), + m_hServerRunningEvent(NULL), + m_hServerRunningMutex(NULL), + m_hSessionsLock(NULL), + m_nLastClientID(0), + m_nErrorState(XN_STATUS_OK), + m_sensorsManager(strConfigFile) +{ +} + +XnSensorServer::~XnSensorServer() +{ + ShutdownServer(); +} + +XnStatus XnSensorServer::Run() +{ + //Initialize server + XnStatus nRetVal = InitServer(); + + if (nRetVal == XN_STATUS_OK) + { + //Initialization succeeded - run main loop + nRetVal = ServerMainLoop(); + } + + //Shutdown the server + ShutdownServer(); + + return nRetVal; +} + +XnBool XnSensorServer::IsServerRunning() +{ + if (m_hServerRunningEvent == NULL) + { + return FALSE; + } + + //Poll the Server Running event + return xnOSIsEventSet(m_hServerRunningEvent); +} + +XnStatus XnSensorServer::InitServer() +{ + XnStatus nRetVal = XN_STATUS_OK; + nRetVal = xnOSCreateNamedMutex(&m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_NAME); + XN_IS_STATUS_OK(nRetVal); + + XnAutoMutexLocker serverRunningLock(m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); + nRetVal = serverRunningLock.GetStatus(); + if (nRetVal != XN_STATUS_OK) + { + //This could mean there's another server/client that's frozen and they're jamming the mutex... + xnLogError(XN_MASK_SENSOR_SERVER, "Failed to lock server mutex: %s - exiting.", xnGetStatusString(nRetVal)); + XN_ASSERT(FALSE); + return XN_STATUS_OS_MUTEX_TIMEOUT; + } + + //From now on we're protected by m_hServerRunningMutex until we return from this function + + /*Create the Server Running event. + This is created as a manual-reset event, because only the server resets it when it's shutting down. */ + nRetVal = xnOSOpenNamedEvent(&m_hServerRunningEvent, XN_SENSOR_SERVER_RUNNING_EVENT_NAME); + if (nRetVal != XN_STATUS_OK) + { + nRetVal = xnOSCreateNamedEvent(&m_hServerRunningEvent, XN_SENSOR_SERVER_RUNNING_EVENT_NAME, TRUE); + XN_IS_STATUS_OK(nRetVal); + } + + if (IsServerRunning()) + { + //Another server is already running. + xnLogInfo(XN_MASK_SENSOR_SERVER, "Detected another server running - exiting."); + xnOSCloseEvent(&m_hServerRunningEvent); + m_hServerRunningEvent = NULL; + return XN_STATUS_DEVICE_SERVER_ALREADY_RUNNING; + } + + nRetVal = m_sensorsManager.Init(); + XN_IS_STATUS_OK(nRetVal); + + // init network + nRetVal = xnOSInitNetwork(); + XN_IS_STATUS_OK(nRetVal); + + // create lock + nRetVal = xnOSCreateCriticalSection(&m_hSessionsLock); + XN_IS_STATUS_OK(nRetVal); + + // create the listen socket + nRetVal = xnOSCreateSocket(XN_OS_TCP_SOCKET, XN_SENSOR_SERVER_IP_ADDRESS, XN_SENSOR_SERVER_PORT, &m_hListenSocket); + XN_IS_STATUS_OK(nRetVal); + + // bind it + nRetVal = xnOSBindSocket(m_hListenSocket); + XN_IS_STATUS_OK(nRetVal); + + // start listening + nRetVal = xnOSListenSocket(m_hListenSocket); + XN_IS_STATUS_OK(nRetVal); + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Server is now listening"); + + /*Set the event to signal that the server is ready for requests. We do this AFTER we start listening so + the clients can wait on the event and then connect to the server socket. */ + nRetVal = xnOSSetEvent(m_hServerRunningEvent); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorServer::ServerMainLoop() +{ + XnStatus nRetVal = XN_STATUS_OK; + XnUInt64 nNow = 0; + XnUInt64 nLastClientRemovedTimestamp = 0; + XnBool bQuit = FALSE; + XN_SOCKET_HANDLE hClientSocket = NULL; + XnBool bNoClients = FALSE; + + xnOSGetTimeStamp(&nLastClientRemovedTimestamp); + + while (!bQuit) + { + nRetVal = xnOSAcceptSocket(m_hListenSocket, &hClientSocket, XN_SENSOR_SERVER_ACCEPT_CONNECTION_TIMEOUT); + if (nRetVal == XN_STATUS_OK) + { + xnLogInfo(XN_MASK_SENSOR_SERVER, "New client trying to connect..."); + + //TODO: Check if we don't have too many clients + nRetVal = AddSession(hClientSocket); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to add new client: %s", xnGetStatusString(nRetVal)); + xnOSCloseSocket(hClientSocket); + //Still in loop + } + } + else // no client trying to connect, do some clean up work + { + if (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT) + { + //Any other error beside timeout is not expected, but we treat it the same. + xnLogWarning(XN_MASK_SENSOR_SERVER, "failed to accept connection: %s", xnGetStatusString(nRetVal)); + } + + // clean sensors + m_sensorsManager.CleanUp(); + + // remove all non-active sessions + XnAutoCSLocker locker(m_hSessionsLock); + if (!m_sessions.IsEmpty()) + { + XnSessionsList::Iterator it = m_sessions.begin(); + while (it != m_sessions.end()) + { + XnSessionsList::Iterator curr = it; + ++it; + + XnServerSession* pSession = *curr; + if (pSession->HasEnded()) + { + nRetVal = RemoveSession(curr); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "failed to remove session: %s", xnGetStatusString(nRetVal)); + } + } + } + + if (m_sessions.IsEmpty()) + { + xnOSGetHighResTimeStamp(&nLastClientRemovedTimestamp); + } + } + else + { + // no sessions + XnUInt64 nNow; + xnOSGetTimeStamp(&nNow); + if (!m_sensorsManager.HasOpenSensors() && (nNow - nLastClientRemovedTimestamp) > m_sensorsManager.GetTimeout()) + { + // shutdown + xnLogInfo(XN_MASK_SENSOR_SERVER, "No sensors are open and no client is connected for %llu ms. Shutting down...", m_sensorsManager.GetTimeout()); + bQuit = TRUE; + } + } + } // clean up + } // main loop + + return XN_STATUS_OK; +} + +void XnSensorServer::ShutdownServer() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoMutexLocker serverRunningLock(m_hServerRunningMutex, XN_SENSOR_SERVER_RUNNING_MUTEX_TIMEOUT); + nRetVal = serverRunningLock.GetStatus(); + if (nRetVal != XN_STATUS_OK) + { + //This could mean there's another server/client that's frozen and they're jamming the mutex... + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to lock server mutex: %s - proceeding with shutdown.", xnGetStatusString(nRetVal)); + XN_ASSERT(FALSE); + } + + if (m_hServerRunningEvent != NULL) + { + nRetVal = xnOSResetEvent(m_hServerRunningEvent); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to reset sensor server event: %s - proceeding with shutdown.", xnGetStatusString(nRetVal)); + XN_ASSERT(FALSE); + } + + xnOSCloseEvent(&m_hServerRunningEvent); + m_hServerRunningEvent = NULL; + } + + XN_ASSERT(m_sessions.IsEmpty()); + + if (m_hListenSocket != NULL) + { + xnOSCloseSocket(m_hListenSocket); + m_hListenSocket = NULL; + } + + if (m_hSessionsLock != NULL) + { + xnOSCloseCriticalSection(&m_hSessionsLock); + m_hSessionsLock = NULL; + } +} + +XnStatus XnSensorServer::AddSession(XN_SOCKET_HANDLE hClientSocket) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUInt32 nID = 0; + + { + XnAutoCSLocker locker(m_hSessionsLock); + ++m_nLastClientID; + nID = m_nLastClientID; + } + + // create new session + XnServerSession* pSession; + XN_VALIDATE_NEW(pSession, XnServerSession, &m_sensorsManager, nID, hClientSocket, &m_logger); + + nRetVal = pSession->Init(); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pSession); + return (nRetVal); + } + + // add it to list in a lock + { + XnAutoCSLocker locker(m_hSessionsLock); + nRetVal = m_sessions.AddLast(pSession); + } + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pSession); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorServer::RemoveSession(XnSessionsList::ConstIterator it) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnServerSession* pSession = *it; + + XnUInt32 nID = pSession->ID(); + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Removing client %u...", nID); + + { + XnAutoCSLocker locker(m_hSessionsLock); + nRetVal = m_sessions.Remove(it); + XN_IS_STATUS_OK(nRetVal); + } + + pSession->Free(); + XN_DELETE(pSession); + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u removed", nID); + + return (XN_STATUS_OK); +} + +XN_DEVICE_API XnStatus XnSensorServerGetGlobalConfigFile(const XnChar* strConfigDir, XnChar* strConfigFile, XnUInt32 nBufSize) +{ + return XnSensor::ResolveGlobalConfigFileName(strConfigFile, nBufSize, strConfigDir); +} + +XN_DEVICE_API XnStatus XnSensorServerRun(const XnChar* strConfigFile) +{ + XnSensorServer server(strConfigFile); + return server.Run(); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorServer.h b/Source/XnDeviceSensorV2/XnSensorServer.h index 1792a9f..a12ac34 100644 --- a/Source/XnDeviceSensorV2/XnSensorServer.h +++ b/Source/XnDeviceSensorV2/XnSensorServer.h @@ -1,138 +1,77 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_SERVER_H__ -#define __XN_SENSOR_SERVER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include "XnSensor.h" -#include -#include "XnSensorClientServer.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_CONFIG_FILE_SERVER_SECTION "Server" - -//--------------------------------------------------------------------------- -// XnSensorServer class -//--------------------------------------------------------------------------- -class XnServerStreamsHash; - -class XnSensorServer -{ -public: - XnSensorServer(); - ~XnSensorServer(); - - XnStatus Run(const XnChar* strConfigFile); - XnBool IsServerRunning(); - -private: - struct XnClient; // Forward Declaration - - XnStatus InitServer(const XnChar* strConfigFile); - XnStatus ServerMainLoop(); - void ShutdownServer(); - XnStatus OpenSensor(const XnChar* strConnectionString); - XnStatus SendInitialState(XnClient* pClient); - XnStatus ServeClient(XnClient* pClient); - XnStatus SendReply(XnClient* pClient, XnSensorServerCustomMessages Type, XnStatus nRC, XnUInt32 nDataSize = 0, void* pAdditionalData = NULL); - XnStatus HandleSingleRequest(XnClient* pClient); - XnStatus HandleOpenSensor(XnClient* pClient); - XnStatus HandleSetIntProperty(XnClient* pClient); - XnStatus HandleSetRealProperty(XnClient* pClient); - XnStatus HandleSetStringProperty(XnClient* pClient); - XnStatus HandleSetGeneralProperty(XnClient* pClient); - XnStatus HandleGetIntProperty(XnClient* pClient); - XnStatus HandleGetRealProperty(XnClient* pClient); - XnStatus HandleGetStringProperty(XnClient* pClient); - XnStatus HandleGetGeneralProperty(XnClient* pClient); - XnStatus HandleConfigFromINIFile(XnClient* pClient); - XnStatus HandleBatchConfig(XnClient* pClient); - XnStatus HandleNewStream(XnClient* pClient); - XnStatus HandleRemoveStream(XnClient* pClient); - XnStatus HandleReadStream(XnClient* pClient); - XnStatus HandleSetStreamState(XnClient* pClient, XnBool bOpen); - - XnStatus AddClient(XN_SOCKET_HANDLE hClientSocket); - XnStatus RemoveClientStream(XnClient* pClient, const XnChar* strName); - XnStatus RemoveClient(XnClient* pClient); - XnStatus ReadStreams(); - XnStatus ReturnToDefaults(); - - XnStatus OnStreamAdded(const XnChar* StreamName); - XnStatus OnStreamRemoved(const XnChar* StreamName); - XnStatus OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType); - XnStatus OnPropertyChanged(const XnProperty* pProp); - XnStatus OnNewServerEvent(const XnUChar* pData, XnUInt32 nDataSize, XnClient* pClient); - XnStatus OnNewStreamData(const XnChar* StreamName); - - XnStatus RegisterToProps(XnPropertySet* pProps); - - void DumpMessage(const XnChar* strType, XnUInt32 nSize = 0, XnUInt32 nClientID = 0, const XnChar* strComment = ""); - - static XN_THREAD_PROC ClientThread(XN_THREAD_PARAM pThreadParam); - static XN_THREAD_PROC ReaderThread(XN_THREAD_PARAM pThreadParam); - - static void XN_CALLBACK_TYPE StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie); - static XnStatus XN_CALLBACK_TYPE PropertyChangedCallback(const XnProperty* pProp, void* pCookie); - static void XN_CALLBACK_TYPE NewServerEventCallback(const XnUChar* pData, XnUInt32 nDataSize, void* pCookie); - static void XN_CALLBACK_TYPE NewStreamDataCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, void* pCookie); - static XnStatus XN_CALLBACK_TYPE StartNewLogCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); - - XN_DECLARE_LIST(XnClient*, XnClientsList); - XnStatus OnIntPropertyChangedInternally(const XnChar* strPropName, XnUInt64 nValue, XnBool& bPassPropToClients); - XnStatus OnRealPropertyChangedInternally(const XnChar* strPropName, XnDouble dValue, XnBool& bPassPropToClients); - XnStatus OnStringPropertyChangedInternally(const XnChar* strPropName, const XnChar* strValue, XnBool &bPassPropToClients); - XnStatus OnGeneralPropertyChangedInternally(const XnChar* strPropName, const XnGeneralBuffer &gbValue, XnBool& bPassPropToClients); - XN_SOCKET_HANDLE m_hListenSocket; - XN_THREAD_HANDLE m_hReaderThread; - XN_EVENT_HANDLE m_hNewDataEvent; - - XN_EVENT_HANDLE m_hServerRunningEvent; //This event is set as long as the server is running and servicing requests - XN_MUTEX_HANDLE m_hServerRunningMutex; //This mutex protects m_hServerRunningEvent - XN_CRITICAL_SECTION_HANDLE m_hSensorLock; - XN_CRITICAL_SECTION_HANDLE m_hBroadcastingLock; - XN_CRITICAL_SECTION_HANDLE m_hClientsCriticalSection; - - XnClientsList m_clients; - XnBool m_bSensorOpen; - XnSensor m_sensor; - XnPropertySetData m_allStreamsProps; - XnServerStreamsHash* m_pServerStreams; - XnUInt32 m_nLastClientID; - XnDump m_serverDump; - XnStatus m_nErrorState; - - XnActualIntProperty m_noClientTimeout; - XnIntProperty m_startNewLog; -}; - -#endif //__XN_SENSOR_SERVER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SENSOR_SERVER_H__ +#define __XN_SENSOR_SERVER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include "XnSensor.h" +#include +#include "XnSensorClientServer.h" +#include "XnServerLogger.h" +#include "XnSensorsManager.h" +#include "XnServerSession.h" + +//--------------------------------------------------------------------------- +// XnSensorServer class +//--------------------------------------------------------------------------- +class XnServerStreamsHash; + +class XnSensorServer +{ +public: + XnSensorServer(const XnChar* strConfigFile); + ~XnSensorServer(); + + XnStatus Run(); + XnBool IsServerRunning(); + +private: + + XnStatus InitServer(); + XnStatus ServerMainLoop(); + void ShutdownServer(); + + XN_DECLARE_LIST(XnServerSession*, XnSessionsList); + + XnStatus AddSession(XN_SOCKET_HANDLE hClientSocket); + XnStatus RemoveSession(XnSessionsList::ConstIterator it); + XnStatus ReturnToDefaults(); + + XN_SOCKET_HANDLE m_hListenSocket; + + XN_EVENT_HANDLE m_hServerRunningEvent; //This event is set as long as the server is running and servicing requests + XN_MUTEX_HANDLE m_hServerRunningMutex; //This mutex protects m_hServerRunningEvent + XN_CRITICAL_SECTION_HANDLE m_hSessionsLock; + + XnSessionsList m_sessions; + XnUInt32 m_nLastClientID; + XnStatus m_nErrorState; + + // new stuff + XnSensorsManager m_sensorsManager; + XnServerLogger m_logger; +}; + +#endif //__XN_SENSOR_SERVER_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorServerRunner.h b/Source/XnDeviceSensorV2/XnSensorServerRunner.h index 97c1cae..8000f2a 100644 --- a/Source/XnDeviceSensorV2/XnSensorServerRunner.h +++ b/Source/XnDeviceSensorV2/XnSensorServerRunner.h @@ -1,36 +1,31 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_SERVER_RUNNER_H__ -#define __XN_SENSOR_SERVER_RUNNER_H__ - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- -XN_DEVICE_API XnStatus XnSensorServerGetGlobalConfigFile(const XnChar* strConfigDir, XnChar* strConfigFile, XnUInt32 nBufSize); -XN_DEVICE_API XnStatus XnSensorServerRun(const XnChar* strConfigFile); - -#endif //__XN_SENSOR_SERVER_RUNNER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SENSOR_SERVER_RUNNER_H__ +#define __XN_SENSOR_SERVER_RUNNER_H__ + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- +XN_DEVICE_API XnStatus XnSensorServerGetGlobalConfigFile(const XnChar* strConfigDir, XnChar* strConfigFile, XnUInt32 nBufSize); +XN_DEVICE_API XnStatus XnSensorServerRun(const XnChar* strConfigFile); + +#endif //__XN_SENSOR_SERVER_RUNNER_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorStreamHelper.cpp b/Source/XnDeviceSensorV2/XnSensorStreamHelper.cpp index 847929a..003808e 100644 --- a/Source/XnDeviceSensorV2/XnSensorStreamHelper.cpp +++ b/Source/XnDeviceSensorV2/XnSensorStreamHelper.cpp @@ -1,441 +1,441 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSensorStreamHelper.h" -#include "XnStreamProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorStreamHelperCookie -{ -public: - XnSensorStreamHelperCookie(XnActualIntProperty* pStreamProp, XnActualIntProperty* pFirmwareProp, XnBool bAllowWhileOpen, XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc) : - pStreamProp(pStreamProp), pFirmwareProp(pFirmwareProp), bAllowWhileOpen(bAllowWhileOpen), pStreamToFirmwareFunc(pStreamToFirmwareFunc), bProcessorProp(FALSE) - {} - - XnActualIntProperty* pStreamProp; - XnActualIntProperty* pFirmwareProp; - XnBool bAllowWhileOpen; - XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc; - XnBool bProcessorProp; - - struct - { - XnBool bShouldOpen; - XnBool bChooseProcessor; - } CurrentTransaction; -}; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnSensorStreamHelper::XnSensorStreamHelper(XnSensorObjects* pObjects) : - m_pSensorStream(NULL), - m_pStream(NULL), - m_pObjects(pObjects) -{ -} - -XnSensorStreamHelper::~XnSensorStreamHelper() -{ - Free(); -} - -XnStatus XnSensorStreamHelper::Init(IXnSensorStream* pSensorStream, XnDeviceStream* pStream) -{ - XnStatus nRetVal = XN_STATUS_OK; - - m_pSensorStream = pSensorStream; - m_pStream = pStream; - - nRetVal = m_pSensorStream->MapPropertiesToFirmware(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::Free() -{ - if (m_pStream != NULL) - { - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - } - - for (XnHash::Iterator it = m_FirmwareProperties.begin(); it != m_FirmwareProperties.end(); ++it) - { - XnSensorStreamHelperCookie* pCookie = (XnSensorStreamHelperCookie*)it.Value(); - XN_DELETE(pCookie); - } - - m_FirmwareProperties.Clear(); - - return XN_STATUS_OK; -} - -XnStatus XnSensorStreamHelper::Configure() -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnResolutions nRes; - XnUInt32 nFPS; - m_pSensorStream->GetFirmwareStreamConfig(&nRes, &nFPS); - - // claim the stream - nRetVal = GetFirmware()->GetStreams()->ClaimStream(m_pStream->GetType(), nRes, nFPS, m_pStream); - XN_IS_STATUS_OK(nRetVal); - - // configure the stream - nRetVal = m_pSensorStream->ConfigureStreamImpl(); - if (nRetVal != XN_STATUS_OK) - { - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - return (nRetVal); - } - - // create data processor - XnDataProcessor* pProcessor; - nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); - if (nRetVal != XN_STATUS_OK) - { - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - return (nRetVal); - } - - // and register it - nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); - if (nRetVal != XN_STATUS_OK) - { - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::FinalOpen() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pSensorStream->OpenStreamImpl(); - if (nRetVal != XN_STATUS_OK) - { - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::Open() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // configure the stream - nRetVal = Configure(); - XN_IS_STATUS_OK(nRetVal); - - // and now turn it on - nRetVal = FinalOpen(); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::Close() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = m_pSensorStream->CloseStreamImpl(); - XN_IS_STATUS_OK(nRetVal); - - GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::RegisterDataProcessorProperty(XnActualIntProperty& Property) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // mark it so - XnValue val; - nRetVal = m_FirmwareProperties.Get(&Property, val); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHelperCookie* pCookie = (XnSensorStreamHelperCookie*)val; - pCookie->bProcessorProp = TRUE; - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::MapFirmwareProperty(XnActualIntProperty& Property, XnActualIntProperty& FirmwareProperty, XnBool bAllowChangeWhileOpen, XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc /* = 0 */) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // init data - XnSensorStreamHelperCookie* pCookie; - XN_VALIDATE_NEW(pCookie, XnSensorStreamHelperCookie, &Property, &FirmwareProperty, bAllowChangeWhileOpen, pStreamToFirmwareFunc); - - // add it to the list - nRetVal = m_FirmwareProperties.Set(&Property, pCookie); - if (nRetVal != XN_STATUS_OK) - { - XN_DELETE(pCookie); - return (nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::ConfigureFirmware(XnActualIntProperty& Property) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnHash::Iterator it = m_FirmwareProperties.end(); - nRetVal = m_FirmwareProperties.Find(&Property, it); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); - - XnUInt64 nFirmwareValue = Property.GetValue(); - - if (pPropData->pStreamToFirmwareFunc != NULL) - { - nRetVal = pPropData->pStreamToFirmwareFunc(Property.GetValue(), &nFirmwareValue); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = pPropData->pFirmwareProp->SetValue(nFirmwareValue); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::BeforeSettingFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnHash::Iterator it = m_FirmwareProperties.end(); - nRetVal = m_FirmwareProperties.Find(&Property, it); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); - - pPropData->CurrentTransaction.bShouldOpen = FALSE; - pPropData->CurrentTransaction.bChooseProcessor = FALSE; - - // if stream is closed, we can just update the prop. - if (m_pStream->IsOpen()) - { - // check if we need to close the stream first - if (pPropData->bAllowWhileOpen) - { - // before actual changing it, check if this is a processor property - if (pPropData->bProcessorProp) - { - // lock processor - nRetVal = GetFirmware()->GetStreams()->LockStreamProcessor(m_pStream->GetType(), m_pStream); - XN_IS_STATUS_OK(nRetVal); - pPropData->CurrentTransaction.bChooseProcessor = TRUE; - } - - // OK. change the value - XnUInt64 nFirmwareValue = nValue; - - if (pPropData->pStreamToFirmwareFunc != NULL) - { - nRetVal = pPropData->pStreamToFirmwareFunc(nValue, &nFirmwareValue); - XN_IS_STATUS_OK(nRetVal); - } - - // set the param in firmware - nRetVal = pPropData->pFirmwareProp->SetValue(nFirmwareValue); - XN_IS_STATUS_OK(nRetVal); - - // no need to do anything after property will be set - pPropData->CurrentTransaction.bShouldOpen = FALSE; - } - else - { - // we can't change the firmware param. We should first close the stream - nRetVal = m_pStream->Close(); - XN_IS_STATUS_OK(nRetVal); - - // after property will be set, we need to reopen the stream - pPropData->CurrentTransaction.bShouldOpen = TRUE; - } - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::AfterSettingFirmwareParam(XnActualIntProperty& Property) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnHash::Iterator it = m_FirmwareProperties.end(); - nRetVal = m_FirmwareProperties.Find(&Property, it); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); - - if (pPropData->CurrentTransaction.bShouldOpen) - { - nRetVal = m_pStream->Open(); - XN_IS_STATUS_OK(nRetVal); - } - else if (pPropData->CurrentTransaction.bChooseProcessor) - { - XnDataProcessor* pProcessor = NULL; - nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); - XN_IS_STATUS_OK(nRetVal); - - // and unlock - nRetVal = GetFirmware()->GetStreams()->UnlockStreamProcessor(m_pStream->GetType(), m_pStream); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::SimpleSetFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue) -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = BeforeSettingFirmwareParam(Property, nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = Property.UnsafeUpdateValue(nValue); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = AfterSettingFirmwareParam(Property); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::BeforeSettingDataProcessorProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_pStream->IsOpen()) - { - nRetVal = GetFirmware()->GetStreams()->LockStreamProcessor(m_pStream->GetType(), m_pStream); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::AfterSettingDataProcessorProperty() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_pStream->IsOpen()) - { - XnDataProcessor* pProcessor = NULL; - nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); - XN_IS_STATUS_OK(nRetVal); - - // and unlock - nRetVal = GetFirmware()->GetStreams()->UnlockStreamProcessor(m_pStream->GetType(), m_pStream); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::UpdateFromFirmware(XnActualIntProperty& Property) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnHash::Iterator it = m_FirmwareProperties.end(); - nRetVal = m_FirmwareProperties.Find(&Property, it); - XN_IS_STATUS_OK(nRetVal); - - XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); - nRetVal = pPropData->pStreamProp->UnsafeUpdateValue(pPropData->pFirmwareProp->GetValue()); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -XnStatus XnSensorStreamHelper::BatchConfig(const XnActualPropertiesHash& props) -{ - XnStatus nRetVal = XN_STATUS_OK; - - XnBool bShouldClose = FALSE; - - if (m_pStream->IsOpen()) - { - // check if one of the properties requires to close the stream - for (XnHash::Iterator it = m_FirmwareProperties.begin(); it != m_FirmwareProperties.end(); ++it) - { - XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); - if (!pPropData->bAllowWhileOpen) - { - XnProperty* pProp; - if (XN_STATUS_OK == props.Get(pPropData->pStreamProp->GetName(), pProp)) - { - bShouldClose = TRUE; - break; - } - } - } - } - - if (bShouldClose) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "closing stream before batch config..."); - nRetVal = m_pStream->Close(); - XN_IS_STATUS_OK(nRetVal); - } - - nRetVal = m_pStream->XnDeviceStream::BatchConfig(props); - XN_IS_STATUS_OK(nRetVal); - - if (bShouldClose) - { - xnLogVerbose(XN_MASK_DEVICE_SENSOR, "re-opening stream after batch config..."); - nRetVal = m_pStream->Open(); - XN_IS_STATUS_OK(nRetVal); - } - - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorStreamHelper.h" +#include "XnStreamProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorStreamHelperCookie +{ +public: + XnSensorStreamHelperCookie(XnActualIntProperty* pStreamProp, XnActualIntProperty* pFirmwareProp, XnBool bAllowWhileOpen, XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc) : + pStreamProp(pStreamProp), pFirmwareProp(pFirmwareProp), bAllowWhileOpen(bAllowWhileOpen), pStreamToFirmwareFunc(pStreamToFirmwareFunc), bProcessorProp(FALSE) + {} + + XnActualIntProperty* pStreamProp; + XnActualIntProperty* pFirmwareProp; + XnBool bAllowWhileOpen; + XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc; + XnBool bProcessorProp; + + struct + { + XnBool bShouldOpen; + XnBool bChooseProcessor; + } CurrentTransaction; +}; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnSensorStreamHelper::XnSensorStreamHelper(XnSensorObjects* pObjects) : + m_pSensorStream(NULL), + m_pStream(NULL), + m_pObjects(pObjects) +{ +} + +XnSensorStreamHelper::~XnSensorStreamHelper() +{ + Free(); +} + +XnStatus XnSensorStreamHelper::Init(IXnSensorStream* pSensorStream, XnDeviceStream* pStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + m_pSensorStream = pSensorStream; + m_pStream = pStream; + + nRetVal = m_pSensorStream->MapPropertiesToFirmware(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::Free() +{ + if (m_pStream != NULL) + { + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + } + + for (XnHash::Iterator it = m_FirmwareProperties.begin(); it != m_FirmwareProperties.end(); ++it) + { + XnSensorStreamHelperCookie* pCookie = (XnSensorStreamHelperCookie*)it.Value(); + XN_DELETE(pCookie); + } + + m_FirmwareProperties.Clear(); + + return XN_STATUS_OK; +} + +XnStatus XnSensorStreamHelper::Configure() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnResolutions nRes; + XnUInt32 nFPS; + m_pSensorStream->GetFirmwareStreamConfig(&nRes, &nFPS); + + // claim the stream + nRetVal = GetFirmware()->GetStreams()->ClaimStream(m_pStream->GetType(), nRes, nFPS, m_pStream); + XN_IS_STATUS_OK(nRetVal); + + // configure the stream + nRetVal = m_pSensorStream->ConfigureStreamImpl(); + if (nRetVal != XN_STATUS_OK) + { + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + return (nRetVal); + } + + // create data processor + XnDataProcessor* pProcessor; + nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); + if (nRetVal != XN_STATUS_OK) + { + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + return (nRetVal); + } + + // and register it + nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); + if (nRetVal != XN_STATUS_OK) + { + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::FinalOpen() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pSensorStream->OpenStreamImpl(); + if (nRetVal != XN_STATUS_OK) + { + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::Open() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // configure the stream + nRetVal = Configure(); + XN_IS_STATUS_OK(nRetVal); + + // and now turn it on + nRetVal = FinalOpen(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::Close() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pSensorStream->CloseStreamImpl(); + XN_IS_STATUS_OK(nRetVal); + + GetFirmware()->GetStreams()->ReleaseStream(m_pStream->GetType(), m_pStream); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::RegisterDataProcessorProperty(XnActualIntProperty& Property) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // mark it so + XnValue val; + nRetVal = m_FirmwareProperties.Get(&Property, val); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHelperCookie* pCookie = (XnSensorStreamHelperCookie*)val; + pCookie->bProcessorProp = TRUE; + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::MapFirmwareProperty(XnActualIntProperty& Property, XnActualIntProperty& FirmwareProperty, XnBool bAllowChangeWhileOpen, XnSensorStreamHelper::ConvertCallback pStreamToFirmwareFunc /* = 0 */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // init data + XnSensorStreamHelperCookie* pCookie; + XN_VALIDATE_NEW(pCookie, XnSensorStreamHelperCookie, &Property, &FirmwareProperty, bAllowChangeWhileOpen, pStreamToFirmwareFunc); + + // add it to the list + nRetVal = m_FirmwareProperties.Set(&Property, pCookie); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(pCookie); + return (nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::ConfigureFirmware(XnActualIntProperty& Property) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnHash::Iterator it = m_FirmwareProperties.end(); + nRetVal = m_FirmwareProperties.Find(&Property, it); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); + + XnUInt64 nFirmwareValue = Property.GetValue(); + + if (pPropData->pStreamToFirmwareFunc != NULL) + { + nRetVal = pPropData->pStreamToFirmwareFunc(Property.GetValue(), &nFirmwareValue); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = pPropData->pFirmwareProp->SetValue(nFirmwareValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::BeforeSettingFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnHash::Iterator it = m_FirmwareProperties.end(); + nRetVal = m_FirmwareProperties.Find(&Property, it); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); + + pPropData->CurrentTransaction.bShouldOpen = FALSE; + pPropData->CurrentTransaction.bChooseProcessor = FALSE; + + // if stream is closed, we can just update the prop. + if (m_pStream->IsOpen()) + { + // check if we need to close the stream first + if (pPropData->bAllowWhileOpen) + { + // before actual changing it, check if this is a processor property + if (pPropData->bProcessorProp) + { + // lock processor + nRetVal = GetFirmware()->GetStreams()->LockStreamProcessor(m_pStream->GetType(), m_pStream); + XN_IS_STATUS_OK(nRetVal); + pPropData->CurrentTransaction.bChooseProcessor = TRUE; + } + + // OK. change the value + XnUInt64 nFirmwareValue = nValue; + + if (pPropData->pStreamToFirmwareFunc != NULL) + { + nRetVal = pPropData->pStreamToFirmwareFunc(nValue, &nFirmwareValue); + XN_IS_STATUS_OK(nRetVal); + } + + // set the param in firmware + nRetVal = pPropData->pFirmwareProp->SetValue(nFirmwareValue); + XN_IS_STATUS_OK(nRetVal); + + // no need to do anything after property will be set + pPropData->CurrentTransaction.bShouldOpen = FALSE; + } + else + { + // we can't change the firmware param. We should first close the stream + nRetVal = m_pStream->Close(); + XN_IS_STATUS_OK(nRetVal); + + // after property will be set, we need to reopen the stream + pPropData->CurrentTransaction.bShouldOpen = TRUE; + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::AfterSettingFirmwareParam(XnActualIntProperty& Property) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnHash::Iterator it = m_FirmwareProperties.end(); + nRetVal = m_FirmwareProperties.Find(&Property, it); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); + + if (pPropData->CurrentTransaction.bShouldOpen) + { + nRetVal = m_pStream->Open(); + XN_IS_STATUS_OK(nRetVal); + } + else if (pPropData->CurrentTransaction.bChooseProcessor) + { + XnDataProcessor* pProcessor = NULL; + nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); + XN_IS_STATUS_OK(nRetVal); + + // and unlock + nRetVal = GetFirmware()->GetStreams()->UnlockStreamProcessor(m_pStream->GetType(), m_pStream); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::SimpleSetFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = BeforeSettingFirmwareParam(Property, nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = Property.UnsafeUpdateValue(nValue); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = AfterSettingFirmwareParam(Property); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::BeforeSettingDataProcessorProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pStream->IsOpen()) + { + nRetVal = GetFirmware()->GetStreams()->LockStreamProcessor(m_pStream->GetType(), m_pStream); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::AfterSettingDataProcessorProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pStream->IsOpen()) + { + XnDataProcessor* pProcessor = NULL; + nRetVal = m_pSensorStream->CreateDataProcessor(&pProcessor); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = GetFirmware()->GetStreams()->ReplaceStreamProcessor(m_pStream->GetType(), m_pStream, pProcessor); + XN_IS_STATUS_OK(nRetVal); + + // and unlock + nRetVal = GetFirmware()->GetStreams()->UnlockStreamProcessor(m_pStream->GetType(), m_pStream); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::UpdateFromFirmware(XnActualIntProperty& Property) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnHash::Iterator it = m_FirmwareProperties.end(); + nRetVal = m_FirmwareProperties.Find(&Property, it); + XN_IS_STATUS_OK(nRetVal); + + XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); + nRetVal = pPropData->pStreamProp->UnsafeUpdateValue(pPropData->pFirmwareProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnSensorStreamHelper::BatchConfig(const XnActualPropertiesHash& props) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnBool bShouldClose = FALSE; + + if (m_pStream->IsOpen()) + { + // check if one of the properties requires to close the stream + for (XnHash::Iterator it = m_FirmwareProperties.begin(); it != m_FirmwareProperties.end(); ++it) + { + XnSensorStreamHelperCookie* pPropData = (XnSensorStreamHelperCookie*)it.Value(); + if (!pPropData->bAllowWhileOpen) + { + XnProperty* pProp; + if (XN_STATUS_OK == props.Get(pPropData->pStreamProp->GetName(), pProp)) + { + bShouldClose = TRUE; + break; + } + } + } + } + + if (bShouldClose) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "closing stream before batch config..."); + nRetVal = m_pStream->Close(); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = m_pStream->XnDeviceStream::BatchConfig(props); + XN_IS_STATUS_OK(nRetVal); + + if (bShouldClose) + { + xnLogVerbose(XN_MASK_DEVICE_SENSOR, "re-opening stream after batch config..."); + nRetVal = m_pStream->Open(); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} diff --git a/Source/XnDeviceSensorV2/XnSensorStreamHelper.h b/Source/XnDeviceSensorV2/XnSensorStreamHelper.h index 95ddb78..73feec1 100644 --- a/Source/XnDeviceSensorV2/XnSensorStreamHelper.h +++ b/Source/XnDeviceSensorV2/XnSensorStreamHelper.h @@ -1,127 +1,127 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_SENSOR_STREAM_HELPER_H__ -#define __XN_SENSOR_STREAM_HELPER_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "IXnSensorStream.h" -#include "XnSensorFirmware.h" -#include "XnSensorFixedParams.h" -#include -#include -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSensorStreamHelper -{ -public: - XnSensorStreamHelper(XnSensorObjects* pObjects); - ~XnSensorStreamHelper(); - - XnStatus Init(IXnSensorStream* pSensorStream, XnDeviceStream* pStream); - XnStatus Free(); - - XnStatus Configure(); - XnStatus FinalOpen(); - XnStatus Open(); - XnStatus Close(); - - /** - * Registers a property which affects the data processor. When any of these properties - * changes, the data processor will be recreated. - */ - XnStatus RegisterDataProcessorProperty(XnActualIntProperty& Property); - - typedef XnStatus (*ConvertCallback)(XnUInt64 nSource, XnUInt64* pnDest); - - /** - * Maps a stream property to a firmware property. Later on, such a property can be used - * in calls to ConfigureFirmware or SetStreamFirmwareParam. - */ - XnStatus MapFirmwareProperty(XnActualIntProperty& Property, XnActualIntProperty& FirmwareProperty, XnBool bAllowChangeWhileOpen, ConvertCallback pStreamToFirmwareFunc = 0); - - /** - * Configures the firmware according to the property. This can only be done for properties - * which were previously attached via the MapFirmwareProperty function. - */ - XnStatus ConfigureFirmware(XnActualIntProperty& Property); - - XnStatus BeforeSettingFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue); - XnStatus AfterSettingFirmwareParam(XnActualIntProperty& Property); - - XnStatus BeforeSettingDataProcessorProperty(); - XnStatus AfterSettingDataProcessorProperty(); - - XnStatus SimpleSetFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue); - - XnStatus UpdateFromFirmware(XnActualIntProperty& Property); - - inline XnSensorFirmware* GetFirmware() const { return m_pObjects->pFirmware; } - inline XnFWVer GetFirmwareVersion() const { return GetFirmware()->GetInfo()->nFWVer; } - inline XnSensorFixedParams* GetFixedParams() const { return m_pObjects->pFixedParams; } - inline XnDevicePrivateData* GetPrivateData() const { return m_pObjects->pDevicePrivateData; } - inline XnSensorFPS* GetFPS() const { return m_pObjects->pFPS; } - inline XnCmosInfo* GetCmosInfo() const { return m_pObjects->pCmosInfo; } - inline IXnSensorStream* GetSensorStream() { return m_pSensorStream; } - - inline XnStatus StartFirmwareTransaction() { return GetFirmware()->GetParams()->StartTransaction(); } - inline XnStatus CommitFirmwareTransaction() { return GetFirmware()->GetParams()->CommitTransaction(); } - inline XnStatus CommitFirmwareTransactionAsBatch() { return GetFirmware()->GetParams()->CommitTransactionAsBatch(); } - inline XnStatus RollbackFirmwareTransaction() { return GetFirmware()->GetParams()->RollbackTransaction(); } - - XnStatus BatchConfig(const XnActualPropertiesHash& props); - -private: - IXnSensorStream* m_pSensorStream; - XnDeviceStream* m_pStream; - XnSensorObjects* m_pObjects; - - XnHash m_FirmwareProperties; -}; - -class XnSensorStreamHolder : public XnDeviceModuleHolder -{ -public: - XnSensorStreamHolder(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper) : - XnDeviceModuleHolder(pStream), m_pHelper(pHelper) - {} - - inline XnDeviceStream* GetStream() { return (XnDeviceStream*)GetModule(); } - inline XnSharedMemoryBufferPool* GetSharedBufferPool() { return m_pHelper->GetSensorStream()->GetSharedMemoryBuffer(); } - - XnStatus Configure() { return m_pHelper->Configure(); } - XnStatus FinalOpen() { return m_pHelper->FinalOpen(); } - -private: - XnSensorStreamHelper* m_pHelper; -}; - -#endif //__XN_SENSOR_STREAM_HELPER_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_SENSOR_STREAM_HELPER_H__ +#define __XN_SENSOR_STREAM_HELPER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "IXnSensorStream.h" +#include "XnSensorFirmware.h" +#include "XnSensorFixedParams.h" +#include +#include +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorStreamHelper +{ +public: + XnSensorStreamHelper(XnSensorObjects* pObjects); + ~XnSensorStreamHelper(); + + XnStatus Init(IXnSensorStream* pSensorStream, XnDeviceStream* pStream); + XnStatus Free(); + + XnStatus Configure(); + XnStatus FinalOpen(); + XnStatus Open(); + XnStatus Close(); + + /** + * Registers a property which affects the data processor. When any of these properties + * changes, the data processor will be recreated. + */ + XnStatus RegisterDataProcessorProperty(XnActualIntProperty& Property); + + typedef XnStatus (*ConvertCallback)(XnUInt64 nSource, XnUInt64* pnDest); + + /** + * Maps a stream property to a firmware property. Later on, such a property can be used + * in calls to ConfigureFirmware or SetStreamFirmwareParam. + */ + XnStatus MapFirmwareProperty(XnActualIntProperty& Property, XnActualIntProperty& FirmwareProperty, XnBool bAllowChangeWhileOpen, ConvertCallback pStreamToFirmwareFunc = 0); + + /** + * Configures the firmware according to the property. This can only be done for properties + * which were previously attached via the MapFirmwareProperty function. + */ + XnStatus ConfigureFirmware(XnActualIntProperty& Property); + + XnStatus BeforeSettingFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue); + XnStatus AfterSettingFirmwareParam(XnActualIntProperty& Property); + + XnStatus BeforeSettingDataProcessorProperty(); + XnStatus AfterSettingDataProcessorProperty(); + + XnStatus SimpleSetFirmwareParam(XnActualIntProperty& Property, XnUInt16 nValue); + + XnStatus UpdateFromFirmware(XnActualIntProperty& Property); + + inline XnSensorFirmware* GetFirmware() const { return m_pObjects->pFirmware; } + inline XnFWVer GetFirmwareVersion() const { return GetFirmware()->GetInfo()->nFWVer; } + inline XnSensorFixedParams* GetFixedParams() const { return m_pObjects->pFixedParams; } + inline XnDevicePrivateData* GetPrivateData() const { return m_pObjects->pDevicePrivateData; } + inline XnSensorFPS* GetFPS() const { return m_pObjects->pFPS; } + inline XnCmosInfo* GetCmosInfo() const { return m_pObjects->pCmosInfo; } + inline IXnSensorStream* GetSensorStream() { return m_pSensorStream; } + + inline XnStatus StartFirmwareTransaction() { return GetFirmware()->GetParams()->StartTransaction(); } + inline XnStatus CommitFirmwareTransaction() { return GetFirmware()->GetParams()->CommitTransaction(); } + inline XnStatus CommitFirmwareTransactionAsBatch() { return GetFirmware()->GetParams()->CommitTransactionAsBatch(); } + inline XnStatus RollbackFirmwareTransaction() { return GetFirmware()->GetParams()->RollbackTransaction(); } + + XnStatus BatchConfig(const XnActualPropertiesHash& props); + +private: + IXnSensorStream* m_pSensorStream; + XnDeviceStream* m_pStream; + XnSensorObjects* m_pObjects; + + XnHash m_FirmwareProperties; +}; + +class XnSensorStreamHolder : public XnDeviceModuleHolder +{ +public: + XnSensorStreamHolder(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper) : + XnDeviceModuleHolder(pStream), m_pHelper(pHelper) + {} + + inline XnDeviceStream* GetStream() { return (XnDeviceStream*)GetModule(); } + inline XnSharedMemoryBufferPool* GetSharedBufferPool() { return m_pHelper->GetSensorStream()->GetSharedMemoryBuffer(); } + + XnStatus Configure() { return m_pHelper->Configure(); } + XnStatus FinalOpen() { return m_pHelper->FinalOpen(); } + +private: + XnSensorStreamHelper* m_pHelper; +}; + +#endif //__XN_SENSOR_STREAM_HELPER_H__ diff --git a/Source/XnDeviceSensorV2/XnSensorsManager.cpp b/Source/XnDeviceSensorV2/XnSensorsManager.cpp new file mode 100644 index 0000000..15d27fa --- /dev/null +++ b/Source/XnDeviceSensorV2/XnSensorsManager.cpp @@ -0,0 +1,187 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorsManager.h" +#include "XnSensorClientServer.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_DEFAULT_SERVER_WAIT_FOR_CLIENT_TIME 10000 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnSensorsManager::XnSensorsManager(const XnChar* strGlobalConfigFile) : + m_noClientTimeout(XN_MODULE_PROPERTY_SERVER_NO_CLIENTS_TIMEOUT, XN_SENSOR_DEFAULT_SERVER_WAIT_FOR_CLIENT_TIME), + m_startNewLog(XN_MODULE_PROPERTY_SERVER_START_NEW_LOG_FILE), + m_hLock(NULL) +{ + m_noClientTimeout.UpdateSetCallbackToDefault(); + m_startNewLog.UpdateSetCallback(StartNewLogCallback, this); + + strcpy(m_strGlobalConfigFile, strGlobalConfigFile); +} + +XnSensorsManager::~XnSensorsManager() +{ + Free(); +} + +XnStatus XnSensorsManager::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = xnOSCreateCriticalSection(&m_hLock); + XN_IS_STATUS_OK(nRetVal); + + // read default timeout from file + nRetVal = m_noClientTimeout.ReadValueFromFile(m_strGlobalConfigFile, XN_SENSOR_SERVER_CONFIG_FILE_SECTION); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnSensorsManager::Free() +{ + // close all sensors + while (m_sensors.begin() != m_sensors.end()) + { + ReferencedSensor& sensor = m_sensors.begin().Value(); + XN_DELETE(sensor.pInvoker); + } + + if (m_hLock != NULL) + { + xnOSCloseCriticalSection(&m_hLock); + m_hLock = NULL; + } +} + +XnStatus XnSensorsManager::GetSensor(const XnChar* strDevicePath, XnServerSensorInvoker** ppInvoker) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if the sensor is already open + XnAutoCSLocker locker(m_hLock); + ReferencedSensor* pSensor; + nRetVal = m_sensors.Get(strDevicePath, pSensor); + if (nRetVal == XN_STATUS_NO_MATCH) + { + // not open. open it now + xnLogInfo(XN_MASK_SENSOR_SERVER, "Opening sensor '%s'...", strDevicePath); + + ReferencedSensor sensor; + sensor.nRefCount = 0; + XN_VALIDATE_NEW(sensor.pInvoker, XnServerSensorInvoker); + + XnProperty* aAdditionalProps[] = { &m_noClientTimeout, &m_startNewLog }; + nRetVal = sensor.pInvoker->Init(strDevicePath, m_strGlobalConfigFile, sizeof(aAdditionalProps)/sizeof(XnProperty*), aAdditionalProps); + XN_IS_STATUS_OK(nRetVal); + + // add it to map + nRetVal = m_sensors.Set(sensor.pInvoker->GetDevicePath(), sensor); + XN_IS_STATUS_OK(nRetVal); + + // and take a reference to it + nRetVal = m_sensors.Get(sensor.pInvoker->GetDevicePath(), pSensor); + XN_IS_STATUS_OK(nRetVal); + } + + ++pSensor->nRefCount; + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Sensor '%s' now has %u sessions", pSensor->pInvoker->GetDevicePath(), pSensor->nRefCount); + + *ppInvoker = pSensor->pInvoker; + + return (XN_STATUS_OK); +} + +void XnSensorsManager::ReleaseSensor(XnServerSensorInvoker* pInvoker) +{ + XnAutoCSLocker locker(m_hLock); + ReferencedSensor* pSensor; + XnStatus nRetVal = m_sensors.Get(pInvoker->GetDevicePath(), pSensor); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_SERVER, "Trying to release a sensor that is not in the map!"); + return; + } + + --pSensor->nRefCount; + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Sensor '%s' now has %u sessions", pInvoker->GetDevicePath(), pSensor->nRefCount); + + if (pSensor->nRefCount == 0) + { + // store current time. Then, in CleanUp() if timeout passed, sensor will be closed + xnOSGetTimeStamp(&pSensor->nNoClientsTime); + + // do some clean-up (so that next client will behave as if it started the server) + + // This is a bit ugly, but we need to manually set back to default DEVICE properties + // (we know there aren't any streams and clients, but the Device module always remains) + nRetVal = pSensor->pInvoker->SetIntProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_FRAME_SYNC, (XnUInt64)FALSE); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_SERVER, "Failed resetting FrameSync: %s", xnGetStatusString(nRetVal)); + } + + nRetVal = pSensor->pInvoker->ConfigureModuleFromGlobalFile(XN_MODULE_NAME_DEVICE); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_SERVER, "Failed configuring device from global config file: %s", xnGetStatusString(nRetVal)); + } + } +} + +void XnSensorsManager::CleanUp() +{ + // go over sensors list. each sensor that is not open by any session, and timeout has passed should + // be closed and removed + XnAutoCSLocker locker(m_hLock); + + XnUInt64 nNow; + xnOSGetTimeStamp(&nNow); + XnSensorsHash::Iterator it = m_sensors.begin(); + while (it != m_sensors.end()) + { + XnSensorsHash::Iterator curr = it; + ++it; + + ReferencedSensor& sensor = curr.Value(); + if (sensor.nRefCount == 0 && (nNow - sensor.nNoClientsTime) > m_noClientTimeout.GetValue()) + { + xnLogInfo(XN_MASK_SENSOR_SERVER, "No session holding sensor '%s' for %u ms. Shutting down...", curr.Key(), m_noClientTimeout.GetValue()); + XN_DELETE(sensor.pInvoker); + m_sensors.Remove(curr); + } + } +} + +XnStatus XN_CALLBACK_TYPE XnSensorsManager::StartNewLogCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie) +{ + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Closing current log file..."); + return xnLogStartNewFile(); +} + diff --git a/Source/XnDeviceSensorV2/XnSensorsManager.h b/Source/XnDeviceSensorV2/XnSensorsManager.h new file mode 100644 index 0000000..ed71ad9 --- /dev/null +++ b/Source/XnDeviceSensorV2/XnSensorsManager.h @@ -0,0 +1,71 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SENSORS_MANAGER_H__ +#define __XN_SENSORS_MANAGER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnServerSensorInvoker.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSensorsManager +{ +public: + XnSensorsManager(const XnChar* strGlobalConfigFile); + ~XnSensorsManager(); + + XnStatus Init(); + void Free(); + + XnUInt64 GetTimeout() { return m_noClientTimeout.GetValue(); } + + XnStatus GetSensor(const XnChar* strDevicePath, XnServerSensorInvoker** ppInvoker); + void ReleaseSensor(XnServerSensorInvoker* pInvoker); + + void CleanUp(); + inline XnBool HasOpenSensors() { return m_sensors.begin() != m_sensors.end(); } + +private: + typedef struct + { + XnUInt64 nNoClientsTime; + XnServerSensorInvoker* pInvoker; + XnUInt32 nRefCount; + } ReferencedSensor; + + XN_DECLARE_STRINGS_HASH(ReferencedSensor, XnSensorsHash); + + static XnStatus XN_CALLBACK_TYPE StartNewLogCallback(XnIntProperty* pSender, XnUInt64 nValue, void* pCookie); + + XnChar m_strGlobalConfigFile[XN_FILE_MAX_PATH]; + XN_CRITICAL_SECTION_HANDLE m_hLock; + XnSensorsHash m_sensors; + XnActualIntProperty m_noClientTimeout; + XnIntProperty m_startNewLog; + XnUInt64 nNoClientsTime; +}; + +#endif // __XN_SENSORS_MANAGER_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnServerLogger.h b/Source/XnDeviceSensorV2/XnServerLogger.h new file mode 100644 index 0000000..2616e35 --- /dev/null +++ b/Source/XnDeviceSensorV2/XnServerLogger.h @@ -0,0 +1,58 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SERVER_LOGGER_H__ +#define __XN_SERVER_LOGGER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MASK_SENSOR_SERVER_COMM_DUMP "SensorServerComm" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnServerLogger +{ +public: + inline XnServerLogger() : m_dump(XN_DUMP_CLOSED) + { + xnDumpInit(&m_dump, XN_MASK_SENSOR_SERVER_COMM_DUMP, "TS,Type,Size,Client\n", "%s.csv", XN_MASK_SENSOR_SERVER_COMM_DUMP); + } + + inline void DumpMessage(const XnChar* strType, XnUInt32 nSize = 0, XnUInt32 nClientID = 0, const XnChar* strComment = "") + { + XnUInt64 nNow; + xnOSGetHighResTimeStamp(&nNow); + xnDumpWriteString(m_dump, "%llu,%s,%d,%d,%s\n", nNow, strType, nSize, nClientID, strComment); + } + +private: + XnDump m_dump; +}; + +#endif // __XN_SERVER_LOGGER_H__ + diff --git a/Source/XnDeviceSensorV2/XnServerSensorInvoker.cpp b/Source/XnDeviceSensorV2/XnServerSensorInvoker.cpp new file mode 100644 index 0000000..72ff730 --- /dev/null +++ b/Source/XnDeviceSensorV2/XnServerSensorInvoker.cpp @@ -0,0 +1,649 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnServerSensorInvoker.h" +#include "XnSensorClientServer.h" +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_SENSOR_TERMINATE_READER_THREAD_TIMEOUT 5000 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnServerSensorInvoker::XnServerSensorInvoker() : + m_hSensorLock(NULL), + m_hReaderThread(NULL), + m_hNewDataEvent(NULL), + m_bShouldRun(TRUE), + m_errorState(XN_STATUS_OK) +{ +} + +XnServerSensorInvoker::~XnServerSensorInvoker() +{ + Free(); +} + +XnStatus XnServerSensorInvoker::Init(const XnChar* strDevicePath, const XnChar* strGlobalConfigFile, XnUInt32 nAdditionalProps, XnProperty** aAdditionalProps) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_sensor.SetGlobalConfigFile(strGlobalConfigFile); + XN_IS_STATUS_OK(nRetVal); + + XnDeviceConfig config; + config.DeviceMode = XN_DEVICE_MODE_READ; + config.cpConnectionString = strDevicePath; + config.pInitialValues = NULL; + config.SharingMode = XN_DEVICE_SHARED; + + nRetVal = m_sensor.Init(&config); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_sensor.DeviceModule()->AddProperties(aAdditionalProps, nAdditionalProps); + XN_IS_STATUS_OK(nRetVal); + + // configure from global file + nRetVal = m_sensor.ConfigureModuleFromGlobalFile(XN_MODULE_NAME_DEVICE, XN_SENSOR_SERVER_CONFIG_FILE_SECTION); + XN_IS_STATUS_OK(nRetVal); + + // register to events + nRetVal = m_sensor.OnStreamCollectionChangedEvent().Register(StreamCollectionChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_sensor.OnNewStreamDataEvent().Register(NewStreamDataCallback, this); + XN_IS_STATUS_OK(nRetVal); + + // register to all properties + XN_PROPERTY_SET_CREATE_ON_STACK(props); + nRetVal = m_sensor.DeviceModule()->GetAllProperties(&props); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = RegisterToProps(&props); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateEvent(&m_hNewDataEvent, FALSE); + XN_IS_STATUS_OK(nRetVal); + + // start reader thread + nRetVal = xnOSCreateThread(ReaderThread, this, &m_hReaderThread); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnServerSensorInvoker::Free() +{ + m_bShouldRun = FALSE; + + if (m_hReaderThread != NULL) + { + xnOSWaitAndTerminateThread(&m_hReaderThread, XN_SENSOR_TERMINATE_READER_THREAD_TIMEOUT); + m_hReaderThread = NULL; + } + + XnStatus nRetVal = m_sensor.Destroy(); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to destroy sensor: %s", xnGetStatusString(nRetVal)); + XN_ASSERT(FALSE); + } + + if (m_hNewDataEvent != NULL) + { + xnOSCloseEvent(&m_hNewDataEvent); + m_hNewDataEvent = NULL; + } +} + +const XnChar* XnServerSensorInvoker::GetDevicePath() +{ + return m_sensor.GetUSBPath(); +} + +XnStatus XnServerSensorInvoker::RegisterToProps(XnPropertySet* pProps) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (XnPropertySetData::Iterator itMod = pProps->pData->begin(); itMod != pProps->pData->end(); ++itMod) + { + XnActualPropertiesHash* pHash = itMod.Value(); + + XnDeviceModule* pModule; + nRetVal = m_sensor.FindModule(itMod.Key(), &pModule); + XN_IS_STATUS_OK(nRetVal); + + for (XnActualPropertiesHash::Iterator itProp = pHash->begin(); itProp != pHash->end(); ++itProp) + { + XnProperty* pProp; + nRetVal = pModule->GetProperty(itProp.Key(), &pProp); + XN_IS_STATUS_OK(nRetVal); + + // no need to keep the handle. We only want to unregister when the stream is destroyed, and then + // it happens anyway. + nRetVal = pProp->OnChangeEvent().Register(PropertyChangedCallback, this); + XN_IS_STATUS_OK(nRetVal); + } + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::GetIntProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64* pnValue) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.GetProperty(strModule, strProperty, pnValue); +} + +XnStatus XnServerSensorInvoker::GetRealProperty( const XnChar* strModule, const XnChar* strProperty, XnDouble* pdValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.GetProperty(strModule, strProperty, pdValue); +} + +XnStatus XnServerSensorInvoker::GetStringProperty( const XnChar* strModule, const XnChar* strProperty, XnChar* strValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.GetProperty(strModule, strProperty, strValue); +} + +XnStatus XnServerSensorInvoker::GetGeneralProperty( const XnChar* strModule, const XnChar* strProperty, XnGeneralBuffer& gbValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.GetProperty(strModule, strProperty, gbValue); +} + +XnStatus XnServerSensorInvoker::SetIntProperty( const XnChar* strModule, const XnChar* strProperty, XnUInt64 nValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.SetProperty(strModule, strProperty, nValue); +} + +XnStatus XnServerSensorInvoker::SetRealProperty( const XnChar* strModule, const XnChar* strProperty, XnDouble dValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.SetProperty(strModule, strProperty, dValue); +} + +XnStatus XnServerSensorInvoker::SetStringProperty( const XnChar* strModule, const XnChar* strProperty, const XnChar* strValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.SetProperty(strModule, strProperty, strValue); +} + +XnStatus XnServerSensorInvoker::SetGeneralProperty( const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue ) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.SetProperty(strModule, strProperty, gbValue); +} + +XnStatus XnServerSensorInvoker::GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams, const XnChar* strModule) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.GetAllProperties(pSet, bNoStreams, strModule); +} + +XnStatus XnServerSensorInvoker::LoadConfigFromFile(const XnChar* strFileName, const XnChar* strSectionName) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.LoadConfigFromFile(strFileName, strSectionName); +} + +XnStatus XnServerSensorInvoker::BatchConfig(const XnPropertySet* pChangeSet) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.BatchConfig(pChangeSet); +} + +XnStatus XnServerSensorInvoker::ConfigureModuleFromGlobalFile(const XnChar* strModule) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.ConfigureModuleFromGlobalFile(strModule); +} + +XnStatus XnServerSensorInvoker::CreateStreamData(const XnChar* strStreamName, XnStreamData** ppStreamData) +{ + XnAutoCSLocker lock(m_hSensorLock); + return m_sensor.CreateStreamData(strStreamName, ppStreamData); +} + +XnStatus XnServerSensorInvoker::GetStream(const XnChar* strType, const XnPropertySet* pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // check if stream already exists + XnAutoCSLocker locker(m_hSensorLock); + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(strType, pStream); + if (nRetVal == XN_STATUS_OK) + { + // stream already exists. add ref to it, and try to configure it according to request + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s already exists.", strType); + + // configure it + if (pInitialValues != NULL) + { + nRetVal = m_sensor.BatchConfig(pInitialValues); + XN_IS_STATUS_OK(nRetVal); + } + } + else if (nRetVal == XN_STATUS_NO_MATCH) + { + // stream doesn't exist. create it (more happens in the OnStreamAdded event handler) + nRetVal = m_sensor.CreateStream(strType, strType, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + // now take it from the hash + nRetVal = m_streams.Get(strType, pStream); + XN_IS_STATUS_OK(nRetVal); + } + else + { + return (nRetVal); + } + + ++pStream->nRefCount; + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s now has %u clients.", strType, pStream->nRefCount); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::ReleaseStream(const XnChar* strType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoCSLocker locker(m_hSensorLock); + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(strType, pStream); + XN_IS_STATUS_OK(nRetVal); + + --pStream->nRefCount; + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Stream %s now has %u clients", strType, pStream->nRefCount); + + if (pStream->nRefCount == 0) + { + m_sensor.CloseStream(strType); + m_sensor.DestroyStream(strType); + + // the rest will be done in the OnStreamRemoved event handler... + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OpenStream(const XnChar* strName, NewStreamDataHandler pNewDataHandler, void* pCookie, XnCallbackHandle* phCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoCSLocker locker(m_hSensorLock); + + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + // register for new data event + nRetVal = pStream->pNewDataEvent->Register(pNewDataHandler, pCookie, phCallback); + XN_IS_STATUS_OK(nRetVal); + + // increase open ref count + ++pStream->nOpenRefCount; + + if (pStream->nOpenRefCount == 1) // first one to open + { + // open it + nRetVal = m_sensor.OpenStream(strName); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_SERVER, "Failed to open stream: %s", xnGetStatusString(nRetVal)); + --pStream->nOpenRefCount; + pStream->pNewDataEvent->Unregister(*phCallback); + return (nRetVal); + } + } + + xnLogInfo(XN_MASK_SENSOR_SERVER, "Stream %s is now open by %u clients.", strName, pStream->nOpenRefCount); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::CloseStream(const XnChar* strName, XnCallbackHandle hCallback) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoCSLocker locker(m_hSensorLock); + + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + // decrease open ref count + --pStream->nOpenRefCount; + + xnLogInfo(XN_MASK_SENSOR_SERVER, "Stream %s is now open by %u clients.", strName, pStream->nOpenRefCount); + + // check if we actually need to close it + if (pStream->nOpenRefCount == 0) + { + nRetVal = m_sensor.CloseStream(strName); + if (nRetVal != XN_STATUS_OK) + { + xnLogError(XN_MASK_SENSOR_SERVER, "Failed to close stream: %s", xnGetStatusString(nRetVal)); + ++pStream->nOpenRefCount; + return (nRetVal); + } + } + + // unregister from event + pStream->pNewDataEvent->Unregister(hCallback); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::AddRefFrameBuffer(const XnChar* strStreamName, XnBuffer* pBuffer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnSharedMemoryBufferPool* pBufferPool = NULL; + nRetVal = m_sensor.GetSharedBufferPool(strStreamName, &pBufferPool); + XN_IS_STATUS_OK(nRetVal); + + pBufferPool->AddRef(pBuffer); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::ReleaseFrameBuffer(const XnChar* strStreamName, XnBuffer* pBuffer) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnSharedMemoryBufferPool* pBufferPool = NULL; + nRetVal = m_sensor.GetSharedBufferPool(strStreamName, &pBufferPool); + XN_IS_STATUS_OK(nRetVal); + + pBufferPool->DecRef(pBuffer); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::ReadStream(XnStreamData* pStreamData, XnUInt32* pnOffset) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoCSLocker locker(m_hSensorLock); + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(pStreamData->StreamName, pStream); + XN_IS_STATUS_OK(nRetVal); + + XnSharedMemoryBufferPool* pBufferPool = NULL; + nRetVal = m_sensor.GetSharedBufferPool(pStreamData->StreamName, &pBufferPool); + XN_IS_STATUS_OK(nRetVal); + + // dec ref old data + if (pStreamData->pInternal->pLockedBuffer != NULL) + { + pBufferPool->DecRef(pStreamData->pInternal->pLockedBuffer); + } + + // "read" + pStreamData->nDataSize = pStream->pStreamData->nDataSize; + pStreamData->nFrameID = pStream->pStreamData->nFrameID; + pStreamData->nTimestamp = pStream->pStreamData->nTimestamp; + pStreamData->pData = pStream->pStreamData->pData; + pStreamData->pInternal->pLockedBuffer = pStream->pStreamData->pInternal->pLockedBuffer; + + // add ref to new data + if (pStreamData->pInternal->pLockedBuffer != NULL) + { + pBufferPool->AddRef(pStreamData->pInternal->pLockedBuffer); + } + + *pnOffset = pBufferPool->GetBufferOffset(pStreamData->pInternal->pLockedBuffer); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OnPropertyChanged(const XnProperty* pProp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // some special handling + if (strcmp(pProp->GetName(), XN_STREAM_PROPERTY_STATE) == 0) + { + // ignore STATE property (every client has its own value) + return XN_STATUS_OK; + } + else if (strcmp(pProp->GetName(), XN_MODULE_PROPERTY_ERROR_STATE) == 0) + { + XnActualIntProperty* pActualIntProp = (XnActualIntProperty*)pProp; + XnStatus nOldErrorState = m_errorState; + m_errorState = (XnStatus)pActualIntProp->GetValue(); + switch (m_errorState) + { + case XN_STATUS_DEVICE_NOT_CONNECTED: + //TODO: Handle disconnection + break; + case XN_STATUS_OK: + if (nOldErrorState == XN_STATUS_DEVICE_NOT_CONNECTED) + { + //TODO: Handle re-connection + break; + } + } + } + + // raise event + m_propChangedEvent.Raise(pProp); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OnStreamAdded(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // get all props + XN_PROPERTY_SET_CREATE_ON_STACK(props); + nRetVal = m_sensor.GetAllProperties(&props, FALSE, StreamName); + XN_IS_STATUS_OK(nRetVal); + + // register to all props + nRetVal = RegisterToProps(&props); + XN_IS_STATUS_OK(nRetVal); + + XnActualPropertiesHash* pStreamProps = props.pData->begin().Value(); + + // take type + XnProperty* pProp = NULL; + nRetVal = pStreamProps->Get(XN_STREAM_PROPERTY_TYPE, pProp); + XN_IS_STATUS_OK(nRetVal); + + XnActualStringProperty* pTypeProp = (XnActualStringProperty*)pProp; + + // create stream data + SensorInvokerStream serverStream; + xnOSMemSet(&serverStream, 0, sizeof(serverStream)); + strcpy(serverStream.strType, StreamName); + + XN_VALIDATE_NEW(serverStream.pNewDataEvent, NewStreamDataEvent); + + nRetVal = m_sensor.CreateStreamData(StreamName, &serverStream.pStreamData); + if (nRetVal != XN_STATUS_OK) + { + XN_DELETE(serverStream.pNewDataEvent); + return (nRetVal); + } + + nRetVal = m_streams.Set(StreamName, serverStream); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OnStreamRemoved(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // no need to unregister from its props - they do not exist anymore. + + // remove stream data + SensorInvokerStream* pServerStream; + nRetVal = m_streams.Get(StreamName, pServerStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_sensor.DestroyStreamData(&pServerStream->pStreamData); + XN_IS_STATUS_OK(nRetVal); + + XN_DELETE(pServerStream->pNewDataEvent); + + nRetVal = m_streams.Remove(StreamName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType) +{ + XnStatus nRetVal = XN_STATUS_OK; + + switch (EventType) + { + case XN_DEVICE_STREAM_ADDED: + { + nRetVal = OnStreamAdded(StreamName); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_DEVICE_STREAM_DELETED: + { + nRetVal = OnStreamRemoved(StreamName); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "unknown event: %d", EventType); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::OnNewStreamData(const XnChar* StreamName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + { + XnAutoCSLocker locker(m_hSensorLock); + SensorInvokerStream* pStream; + nRetVal = m_streams.Get(StreamName, pStream); + XN_IS_STATUS_OK(nRetVal); + + pStream->bNewData = TRUE; + } + + nRetVal = xnOSSetEvent(m_hNewDataEvent); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSensorInvoker::ReadStreams() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // wait for new data to be available + nRetVal = xnOSWaitEvent(m_hNewDataEvent, XN_NODE_WAIT_FOR_DATA_TIMEOUT); + if (nRetVal == XN_STATUS_OS_EVENT_TIMEOUT) + { + return XN_STATUS_OK; + } + else if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Got error waiting for new data event: %s", xnGetStatusString(nRetVal)); + // but continue anyway + } + + // lock sensor (we iterate over streams list. make sure no stream is added/removed from the list) + { + XnAutoCSLocker locker(m_hSensorLock); + for (XnServerStreamsHash::Iterator it = m_streams.begin(); it != m_streams.end(); ++it) + { + SensorInvokerStream& stream = it.Value(); + + if (stream.bNewData) + { + // ignore audio (it is read by every client) + if (strcmp(stream.strType, XN_STREAM_NAME_AUDIO) != 0) + { + // read this data + nRetVal = m_sensor.ReadStream(stream.pStreamData); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed reading from stream %s (though event was raised): %s", stream.strType, xnGetStatusString(nRetVal)); + stream.bNewData = FALSE; + continue; + } + } + + stream.bNewData = FALSE; + + stream.pNewDataEvent->Raise(stream.strType, stream.pStreamData->nTimestamp, stream.pStreamData->nFrameID); + } + } // streams loop + } // lock + + return (XN_STATUS_OK); +} + +XnStatus XN_CALLBACK_TYPE XnServerSensorInvoker::PropertyChangedCallback(const XnProperty* pProp, void* pCookie) +{ + XnServerSensorInvoker* pThis = (XnServerSensorInvoker*)pCookie; + pThis->OnPropertyChanged(pProp); + return XN_STATUS_OK; +} + +void XN_CALLBACK_TYPE XnServerSensorInvoker::StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie) +{ + XnServerSensorInvoker* pThis = (XnServerSensorInvoker*)pCookie; + pThis->OnStreamCollectionChanged(StreamName, EventType); +} + +void XN_CALLBACK_TYPE XnServerSensorInvoker::NewStreamDataCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, void* pCookie) +{ + XnServerSensorInvoker* pThis = (XnServerSensorInvoker*)pCookie; + pThis->OnNewStreamData(StreamName); +} + +XN_THREAD_PROC XnServerSensorInvoker::ReaderThread(XN_THREAD_PARAM pThreadParam) +{ + XnServerSensorInvoker* pThis = (XnServerSensorInvoker*)pThreadParam; + while (pThis->m_bShouldRun) + { + pThis->ReadStreams(); + } + XN_THREAD_PROC_RETURN(0); +} + diff --git a/Source/XnDeviceSensorV2/XnServerSensorInvoker.h b/Source/XnDeviceSensorV2/XnServerSensorInvoker.h new file mode 100644 index 0000000..fae1373 --- /dev/null +++ b/Source/XnDeviceSensorV2/XnServerSensorInvoker.h @@ -0,0 +1,124 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SERVER_SENSOR_INVOKER_H__ +#define __XN_SERVER_SENSOR_INVOKER_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensor.h" +#include +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +class XnServerSensorInvoker +{ +private: + XN_DECLARE_EVENT_3ARG(NewStreamDataEvent, INewStreamDataEvent, const XnChar*, strStreamName, XnUInt64, nTimestamp, XnUInt32, nFrameID); + +public: + XnServerSensorInvoker(); + ~XnServerSensorInvoker(); + + XnStatus Init(const XnChar* strDevicePath, const XnChar* strGlobalConfigFile, XnUInt32 nAdditionalProps, XnProperty** aAdditionalProps); + void Free(); + + const XnChar* GetDevicePath(); + + XnStatus GetIntProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64* pnValue); + XnStatus GetRealProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble* pdValue); + XnStatus GetStringProperty(const XnChar* strModule, const XnChar* strProperty, XnChar* strValue); + XnStatus GetGeneralProperty(const XnChar* strModule, const XnChar* strProperty, XnGeneralBuffer& gbValue); + + XnStatus SetIntProperty(const XnChar* strModule, const XnChar* strProperty, XnUInt64 nValue); + XnStatus SetRealProperty(const XnChar* strModule, const XnChar* strProperty, XnDouble dValue); + XnStatus SetStringProperty(const XnChar* strModule, const XnChar* strProperty, const XnChar* strValue); + XnStatus SetGeneralProperty(const XnChar* strModule, const XnChar* strProperty, const XnGeneralBuffer& gbValue); + + XnStatus GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams = FALSE, const XnChar* strModule = NULL); + + XnStatus LoadConfigFromFile(const XnChar* strFileName, const XnChar* strSectionName); + XnStatus BatchConfig(const XnPropertySet* pChangeSet); + XnStatus ConfigureModuleFromGlobalFile(const XnChar* strModule); + + XnStatus CreateStreamData(const XnChar* strStreamName, XnStreamData** ppStreamData); + + XnStatus GetStream(const XnChar* strType, const XnPropertySet* pInitialValues); + XnStatus ReleaseStream(const XnChar* strType); + + typedef INewStreamDataEvent::HandlerPtr NewStreamDataHandler; + XnStatus OpenStream(const XnChar* strName, NewStreamDataHandler pNewDataHandler, void* pCookie, XnCallbackHandle* phCallback); + XnStatus CloseStream(const XnChar* strName, XnCallbackHandle hCallback); + + XnStatus AddRefFrameBuffer(const XnChar* strStreamName, XnBuffer* pBuffer); + XnStatus ReleaseFrameBuffer(const XnChar* strStreamName, XnBuffer* pBuffer); + + XnStatus ReadStream(XnStreamData* pStreamData, XnUInt32* pnOffset); + + XN_DECLARE_EVENT_1ARG(PropChangeEvent, IPropChangeEvent, const XnProperty*, pProp); + IPropChangeEvent& PropChangedEvent() { return m_propChangedEvent; } + +private: + // Types + typedef struct SensorInvokerStream + { + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nRefCount; + XnUInt32 nOpenRefCount; + XnStreamData* pStreamData; + XnBool bNewData; + NewStreamDataEvent* pNewDataEvent; + } SensorInvokerStream; + + XN_DECLARE_STRINGS_HASH(SensorInvokerStream, XnServerStreamsHash); + + // Functions + XnStatus RegisterToProps(XnPropertySet* pProps); + + XnStatus OnPropertyChanged(const XnProperty* pProp); + XnStatus OnStreamAdded(const XnChar* StreamName); + XnStatus OnStreamRemoved(const XnChar* StreamName); + XnStatus OnStreamCollectionChanged(const XnChar* StreamName, XnStreamsChangeEventType EventType); + XnStatus OnNewStreamData(const XnChar* StreamName); + XnStatus ReadStreams(); + + static XnStatus XN_CALLBACK_TYPE PropertyChangedCallback(const XnProperty* pProp, void* pCookie); + static void XN_CALLBACK_TYPE StreamCollectionChangedCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, XnStreamsChangeEventType EventType, void* pCookie); + static void XN_CALLBACK_TYPE NewStreamDataCallback(XnDeviceHandle DeviceHandle, const XnChar* StreamName, void* pCookie); + static XN_THREAD_PROC ReaderThread(XN_THREAD_PARAM pThreadParam); + + // Members + XnSensor m_sensor; + XN_CRITICAL_SECTION_HANDLE m_hSensorLock; + XN_THREAD_HANDLE m_hReaderThread; + XN_EVENT_HANDLE m_hNewDataEvent; + volatile XnBool m_bShouldRun; + XnStatus m_errorState; + + PropChangeEvent m_propChangedEvent; + XnServerStreamsHash m_streams; +}; + +#endif // __XN_SERVER_SENSOR_INVOKER_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnServerSession.cpp b/Source/XnDeviceSensorV2/XnServerSession.cpp new file mode 100644 index 0000000..72a5864 --- /dev/null +++ b/Source/XnDeviceSensorV2/XnServerSession.cpp @@ -0,0 +1,1211 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnServerSession.h" +#include "XnSensorClientServer.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnServerSession::XnServerSession(XnSensorsManager* pSensorsManager, XnUInt32 nID, XN_SOCKET_HANDLE hSocket, XnServerLogger* pLogger) : + m_pSensorsManager(pSensorsManager), + m_nID(nID), + m_hSocket(hSocket), + m_hThread(NULL), + m_hCommLock(NULL), + m_hStreamsLock(NULL), + m_ioStream(hSocket), + m_privateIncomingPacker(&m_ioStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE), + m_privateOutgoingPacker(&m_ioStream, XN_SENSOR_SERVER_CONFIG_PACKER_SIZE), + m_pStreamDataSet(NULL), + m_bShouldRun(TRUE), + m_bHasEnded(FALSE), + m_pSensor(NULL), + m_pLogger(pLogger), + m_hProprtyChangeCallback(NULL) +{ + SessionStream stream; + strcpy(stream.strStreamName, XN_MODULE_NAME_DEVICE); + strcpy(stream.strClientStreamName, XN_MODULE_NAME_DEVICE); + stream.bIsOpen = FALSE; + m_streamsHash.Set(XN_MODULE_NAME_DEVICE, stream); +} + +XnServerSession::~XnServerSession() +{ + Free(); +} + +XnStatus XnServerSession::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_privateIncomingPacker.Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_privateOutgoingPacker.Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnStreamDataSetCreate(&m_pStreamDataSet); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateCriticalSection(&m_hCommLock); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = xnOSCreateCriticalSection(&m_hStreamsLock); + XN_IS_STATUS_OK(nRetVal); + + // start thread + nRetVal = xnOSCreateThread(ServeThreadCallback, this, &m_hThread); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnServerSession::Free() +{ + if (m_hThread != NULL) + { + xnOSWaitAndTerminateThread(&m_hThread, 2000); + m_hThread = NULL; + } + + if (m_hStreamsLock != NULL) + { + xnOSCloseCriticalSection(&m_hStreamsLock); + m_hStreamsLock = NULL; + } + + if (m_hCommLock != NULL) + { + xnOSCloseCriticalSection(&m_hCommLock); + m_hCommLock = NULL; + } + + if (m_pStreamDataSet != NULL) + { + XnStreamDataSetDestroy(&m_pStreamDataSet); + m_pStreamDataSet = NULL; + } + + if (m_hSocket != NULL) + { + xnOSCloseSocket(m_hSocket); + m_hSocket = NULL; + } + + m_privateIncomingPacker.Free(); + m_privateOutgoingPacker.Free(); +} + +XnStatus XnServerSession::SendReply(XnSensorServerCustomMessages Type, XnStatus nRC, XnUInt32 nDataSize /* = 0 */, void* pAdditionalData /* = NULL */) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnUChar message[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; + XnSensorClientServerReply* pReply = (XnSensorClientServerReply*)message; + pReply->nRetVal = nRC; + pReply->Type = Type; + pReply->nDataSize = nDataSize; + xnOSMemCopy(pReply->pData, pAdditionalData, nDataSize); + XnUChar* pEnd = pReply->pData + nDataSize; + + m_pLogger->DumpMessage("Reply", nDataSize, m_nID); + + // lock this so that messages don't mix up + { + XnAutoCSLocker lock(m_hCommLock); + nRetVal = m_privateOutgoingPacker.WriteCustomData(Type, message, pEnd - message); + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::SendInitialState() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XN_PROPERTY_SET_CREATE_ON_STACK(props); + + // get it + nRetVal = m_pSensor->GetAllProperties(&props, TRUE); + XN_IS_STATUS_OK(nRetVal); + + // and send it + m_pLogger->DumpMessage("InitialState", 0, m_nID); + + { + XnAutoCSLocker lock(m_hCommLock); + nRetVal = m_privateOutgoingPacker.WritePropertySet(&props); + } + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::FindStreamByServerName(const XnChar* strName, SessionStream** ppStream) +{ + XnStatus nRetVal = XN_STATUS_OK; + + for (SessionStreamsHash::Iterator it = m_streamsHash.begin(); it != m_streamsHash.end(); ++it) + { + SessionStream* pStream = &it.Value(); + if (strcmp(pStream->strStreamName, strName) == 0) + { + *ppStream = pStream; + return XN_STATUS_OK; + } + } + + *ppStream = NULL; + return (XN_STATUS_NO_MATCH); +} + +XnStatus XnServerSession::HandleOpenSensor() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strConnectionString[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR, strConnectionString, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to open sensor %s", m_nID, strConnectionString); + + XnStatus nActionResult = OpenSensorImpl(strConnectionString); + + if (nActionResult == XN_STATUS_OK) + { + // sensor is open. send client its initial state + nActionResult = SendInitialState(); + } + + // if an error occurred, send it to the client + if (nActionResult != XN_STATUS_OK) + { + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::OpenSensorImpl(const XnChar* strConnectionString) +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = m_pSensorsManager->GetSensor(strConnectionString, &m_pSensor); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->PropChangedEvent().Register(PropertyChangedCallback, this, &m_hProprtyChangeCallback); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::CloseSensorImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_pSensor == NULL) + { + return XN_STATUS_OK; + } + + // unregister from events + m_pSensor->PropChangedEvent().Unregister(m_hProprtyChangeCallback); + m_hProprtyChangeCallback = NULL; + + // release all streams + XnAutoCSLocker locker(m_hStreamsLock); + SessionStreamsHash::Iterator it = m_streamsHash.begin(); + while (it != m_streamsHash.end()){ + SessionStreamsHash::Iterator curr = it; + ++it; + const XnChar* strName = curr.Key(); + if (strcmp(strName, XN_MODULE_NAME_DEVICE) != 0) + { + RemoveStreamImpl(strName); + } + else + { + // just remove it from the map + m_streamsHash.Remove(curr); + } + } + + // release sensor + if (m_pSensor != NULL) + { + m_pSensorsManager->ReleaseSensor(m_pSensor); + m_pSensor = NULL; + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleSetIntProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt64 nValue; + nRetVal = m_privateIncomingPacker.ReadProperty(strModule, strProp, &nValue); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = SetIntPropertyImpl(strModule, strProp, nValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::SetIntPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnUInt64 nValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", m_nID, strModule, strProp); + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->SetIntProperty(pStream->strStreamName, strProp, nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleSetRealProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnDouble dValue; + nRetVal = m_privateIncomingPacker.ReadProperty(strModule, strProp, &dValue); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = SetRealPropertyImpl(strModule, strProp, dValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::SetRealPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnDouble dValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", m_nID, strModule, strProp); + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->SetRealProperty(pStream->strStreamName, strProp, dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleSetStringProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = m_privateIncomingPacker.ReadProperty(strModule, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = SetStringPropertyImpl(strModule, strProp, strValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::SetStringPropertyImpl(const XnChar* strModule, const XnChar* strProp, const XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", m_nID, strModule, strProp); + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->SetStringProperty(pStream->strStreamName, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleSetGeneralProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + XnGeneralBuffer gbValue; + nRetVal = m_privateIncomingPacker.ReadProperty(strModule, strProp, &gbValue); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = SetGeneralPropertyImpl(strModule, strProp, gbValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::SetGeneralPropertyImpl(const XnChar* strModule, const XnChar* strProp, const XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to set %s.%s", m_nID, strModule, strProp); + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->SetGeneralProperty(pStream->strStreamName, strProp, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleGetIntProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnSensorServerMessageGetPropertyRequest request; + XnUInt32 nDataSize = sizeof(request); + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, &request, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + if (nDataSize != sizeof(request)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); + } + + // get + XnUInt64 nValue; + XnStatus nActionResult = GetIntPropertyImpl(request.strModuleName, request.strPropertyName, &nValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY, nActionResult, sizeof(nValue), &nValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::GetIntPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnUInt64* pnValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->GetIntProperty(pStream->strStreamName, strProp, pnValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleGetRealProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnSensorServerMessageGetPropertyRequest request; + XnUInt32 nDataSize = sizeof(request); + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, &request, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + if (nDataSize != sizeof(request)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); + } + + // get + XnDouble dValue; + XnStatus nActionResult = GetRealPropertyImpl(request.strModuleName, request.strPropertyName, &dValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY, nActionResult, sizeof(dValue), &dValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::GetRealPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnDouble* pdValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->GetRealProperty(pStream->strStreamName, strProp, pdValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleGetStringProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnSensorServerMessageGetPropertyRequest request; + XnUInt32 nDataSize = sizeof(request); + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, &request, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + if (nDataSize != sizeof(request)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); + } + + // get + XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; + XnStatus nActionResult = GetStringPropertyImpl(request.strModuleName, request.strPropertyName, strValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY, nActionResult, sizeof(strValue), strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::GetStringPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnChar* strValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->GetStringProperty(pStream->strStreamName, strProp, strValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleGetGeneralProperty() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnUChar bufValue[XN_SENSOR_SERVER_MAX_REPLY_SIZE]; + XnSensorServerMessageGetPropertyRequest* pRequest = (XnSensorServerMessageGetPropertyRequest*)bufValue; + XnUChar* pData = bufValue + sizeof(XnSensorServerMessageGetPropertyRequest); + XnUInt32 nDataSize = XN_SENSOR_SERVER_MAX_REPLY_SIZE; + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, bufValue, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + if (nDataSize < sizeof(XnSensorServerMessageGetPropertyRequest)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); + } + + // get + XnGeneralBuffer gbValue = XnGeneralBufferPack(pData, pRequest->nSize); + XnStatus nActionResult = GetGeneralPropertyImpl(pRequest->strModuleName, pRequest->strPropertyName, gbValue); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY, nActionResult, pRequest->nSize, pData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::GetGeneralPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnGeneralBuffer& gbValue) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strModule, pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->GetGeneralProperty(pStream->strStreamName, strProp, gbValue); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleConfigFromINIFile() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnSensorServerMessageIniFile message; + XnUInt32 nDataSize = sizeof(message); + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_INI_FILE, (XnUChar*)&message, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + if (nDataSize != sizeof(message)) + { + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Sensor server protocol error - invalid size!"); + } + + // load + XnStatus nActionResult = ConfigFromINIFileImpl(message.strFileName, message.strSectionName); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::ConfigFromINIFileImpl(const XnChar* strFileName, const XnChar* strSectionName) +{ + return m_pSensor->LoadConfigFromFile(strFileName, strSectionName); +} + +XnStatus XnServerSession::HandleBatchConfig() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XN_PROPERTY_SET_CREATE_ON_STACK(props); + + nRetVal = m_privateIncomingPacker.ReadPropertySet(&props); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = BatchConfigImpl(&props); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::BatchConfigImpl(const XnPropertySet* pProps) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested a batch config", m_nID); + + XN_PROPERTY_SET_CREATE_ON_STACK(serverProps); + for (XnPropertySetData::Iterator it = pProps->pData->begin(); it != pProps->pData->end(); ++it) + { + SessionStream* pStream; + nRetVal = m_streamsHash.Get(it.Key(), pStream); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetCloneModule(pProps, &serverProps, it.Key(), pStream->strStreamName); + XN_IS_STATUS_OK(nRetVal); + } + + nRetVal = m_pSensor->BatchConfig(&serverProps); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleNewStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XN_PROPERTY_SET_CREATE_ON_STACK(props); + + XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = m_privateIncomingPacker.ReadNewStream(strType, strName, &props); + XN_IS_STATUS_OK(nRetVal); + + XnPropertySet* pInitialValues = &props; + if (props.pData->begin() == props.pData->end()) + { + pInitialValues = NULL; + } + + XnStatus nActionResult = NewStreamImpl(strType, strName, pInitialValues); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::NewStreamImpl(const XnChar* strType, const XnChar* strName, const XnPropertySet* pInitialValues) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to create stream '%s' (%s)", m_nID, strName, strType); + + nRetVal = m_pSensor->GetStream(strType, pInitialValues); + XN_IS_STATUS_OK(nRetVal); + + // send client the new stream data + XN_PROPERTY_SET_CREATE_ON_STACK(streamProps); + XN_PROPERTY_SET_CREATE_ON_STACK(clientStreamProps); + + // take properties + nRetVal = m_pSensor->GetAllProperties(&streamProps, FALSE, strType); + XN_IS_STATUS_OK(nRetVal); + + // copy relevant ones + nRetVal = XnPropertySetCloneModule(&streamProps, &clientStreamProps, strType, strName); + XN_IS_STATUS_OK(nRetVal); + + // now change the state property. It should be OFF, and not the real value (each client has + // its own stream state). + nRetVal = XnPropertySetRemoveProperty(&clientStreamProps, strName, XN_STREAM_PROPERTY_STATE); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnPropertySetAddIntProperty(&clientStreamProps, strName, XN_STREAM_PROPERTY_STATE, FALSE); + XN_IS_STATUS_OK(nRetVal); + + m_pLogger->DumpMessage("NewStream", 0, m_nID, strName); + + { + XnAutoCSLocker lock(m_hCommLock); + nRetVal = m_privateOutgoingPacker.WriteNewStream(strType, strName, &clientStreamProps); + } + XN_IS_STATUS_OK(nRetVal); + + // now add it to client data + nRetVal = AddSessionModule(strName, strType); + XN_IS_STATUS_OK(nRetVal); + + // create client stream data + XnStreamData* pStreamData = NULL; + nRetVal = m_pSensor->CreateStreamData(strType, &pStreamData); + XN_IS_STATUS_OK(nRetVal); + + // and add it to set + nRetVal = XnStreamDataSetAdd(m_pStreamDataSet, pStreamData); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleRemoveStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; + nRetVal = m_privateIncomingPacker.ReadStreamRemoved(strName); + XN_IS_STATUS_OK(nRetVal); + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to remove stream %s", m_nID, strName); + XnStatus nActionResult = RemoveStreamImpl(strName); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::RemoveStreamImpl(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + // first close it (so that ref count will be consistent) + if (pStream->bIsOpen) + { + nRetVal = CloseStreamImpl(strName); + XN_IS_STATUS_OK(nRetVal); + pStream->bIsOpen = FALSE; + } + + // release that stream + nRetVal = m_pSensor->ReleaseStream(pStream->strStreamName); + XN_IS_STATUS_OK(nRetVal); + + // if client had a buffer of this stream, release it + XnStreamData* pStreamData = NULL; + nRetVal = XnStreamDataSetGet(m_pStreamDataSet, pStream->strStreamName, &pStreamData); + if (nRetVal == XN_STATUS_OK) + { + if (pStreamData->pInternal->pLockedBuffer != NULL) + { + m_pSensor->ReleaseFrameBuffer(pStream->strStreamName, pStreamData->pInternal->pLockedBuffer); + } + + // free data + XnStreamDataSetRemove(m_pStreamDataSet, pStreamData); + XnStreamDataDestroy(&pStreamData); + } + + // now remove it from client + nRetVal = RemoveSessionModule(strName); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleOpenStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; + XnUInt32 nType = XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM; + nRetVal = m_privateIncomingPacker.ReadCustomData(nType, strStreamName, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = OpenStreamImpl(strStreamName); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::OpenStreamImpl(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to open stream %s", m_nID, strName); + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + if (!pStream->bIsOpen) + { + nRetVal = m_pSensor->OpenStream(pStream->strStreamName, StreamNewDataCallback, pStream, &pStream->hNewDataCallback); + XN_IS_STATUS_OK(nRetVal); + pStream->bIsOpen = TRUE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleCloseStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; + XnUInt32 nType = XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM; + nRetVal = m_privateIncomingPacker.ReadCustomData(nType, strStreamName, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + XnStatus nActionResult = CloseStreamImpl(strStreamName); + + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::CloseStreamImpl(const XnChar* strName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Client %u requested to close stream %s", m_nID, strName); + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + if (pStream->bIsOpen) + { + nRetVal = m_pSensor->CloseStream(pStream->strStreamName, pStream->hNewDataCallback); + XN_IS_STATUS_OK(nRetVal); + pStream->bIsOpen = FALSE; + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleReadStream() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // read it + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + XnUInt32 nDataSize = XN_DEVICE_MAX_STRING_LENGTH; + nRetVal = m_privateIncomingPacker.ReadCustomData(XN_SENSOR_SERVER_MESSAGE_READ_STREAM, strStreamName, &nDataSize); + XN_IS_STATUS_OK(nRetVal); + + XnSensorServerReadReply reply; + XnStatus nActionResult = ReadStreamImpl(strStreamName, &reply); + if (nActionResult == XN_STATUS_OK) + { + m_pLogger->DumpMessage("Data", sizeof(reply), 0, strStreamName); + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_READ_STREAM, XN_STATUS_OK, sizeof(reply), &reply); + XN_IS_STATUS_OK(nRetVal); + } + else + { + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, nActionResult); + XN_IS_STATUS_OK(nRetVal); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::ReadStreamImpl(const XnChar* strName, XnSensorServerReadReply* pReply) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(strName, pStream); + XN_IS_STATUS_OK(nRetVal); + + XnStreamData* pStreamData; + nRetVal = XnStreamDataSetGet(m_pStreamDataSet, pStream->strStreamName, &pStreamData); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_pSensor->ReadStream(pStreamData, &pReply->nOffset); + XN_IS_STATUS_OK(nRetVal); + + pReply->nDataSize = pStreamData->nDataSize; + pReply->nFrameID = pStreamData->nFrameID; + pReply->nTimestamp = pStreamData->nTimestamp; + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleCloseSession() +{ + XnStatus nRetVal = XN_STATUS_OK; + + xnLogVerbose(XN_MASK_SENSOR_SERVER, "Received BYE from client %u", m_nID); + + XnStatus nActionResult = CloseSessionImpl(); + + // client shouldn't care if close succeeded or not. always send OK. + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_BYE, XN_STATUS_OK); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed to send BYE reply to client %u: %s", m_nID, xnGetStatusString(nRetVal)); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::CloseSessionImpl() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // stop processing messages + m_bShouldRun = FALSE; + + // close sensor + nRetVal = CloseSensorImpl(); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::HandleSingleRequest() +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnPackedDataType nType; + nRetVal = m_privateIncomingPacker.ReadNextObject(&nType); + XN_IS_STATUS_OK(nRetVal); + + XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; + + switch (nType) + { + case XN_SENSOR_SERVER_MESSAGE_OPEN_SENSOR: + { + nRetVal = HandleOpenSensor(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_INT_PROPERTY: + { + nRetVal = HandleSetIntProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_REAL_PROPERTY: + { + nRetVal = HandleSetRealProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_STRING_PROPERTY: + { + nRetVal = HandleSetStringProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_GENERAL_PROPERTY: + { + nRetVal = HandleSetGeneralProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_GET_INT_PROPERTY: + { + nRetVal = HandleGetIntProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_GET_REAL_PROPERTY: + { + nRetVal = HandleGetRealProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_GET_STRING_PROPERTY: + { + nRetVal = HandleGetStringProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_GET_GENERAL_PROPERTY: + { + nRetVal = HandleGetGeneralProperty(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_INI_FILE: + { + nRetVal = HandleConfigFromINIFile(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_PROPERTY_SET: + { + nRetVal = HandleBatchConfig(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_NEW_STREAM: + { + nRetVal = HandleNewStream(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PACKED_STREAM_REMOVED: + { + nRetVal = HandleRemoveStream(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_READ_STREAM: + { + nRetVal = HandleReadStream(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_OPEN_STREAM: + { + nRetVal = HandleOpenStream(); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_SENSOR_SERVER_MESSAGE_CLOSE_STREAM: + { + nRetVal = HandleCloseStream(); + XN_IS_STATUS_OK(nRetVal); + break; + } + + case XN_SENSOR_SERVER_MESSAGE_BYE: + { + nRetVal = HandleCloseSession(); + XN_IS_STATUS_OK(nRetVal); + break; + } + + default: + xnLogWarning(XN_MASK_SENSOR_SERVER, "Unknown client request: %d", nType); + nRetVal = SendReply(XN_SENSOR_SERVER_MESSAGE_GENERAL_OP_RESPOND, XN_STATUS_ERROR); + XN_IS_STATUS_OK(nRetVal); + + return XN_STATUS_ERROR; + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::ServeThread() +{ + XnStatus nRetVal = XN_STATUS_OK; + + while (m_bShouldRun) + { + if (!m_ioStream.IsConnected()) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Client %u socket was closed. Closing session...", m_nID); + CloseSessionImpl(); + break; + } + + nRetVal = HandleSingleRequest(); + if ((nRetVal != XN_STATUS_OK) && + (nRetVal != XN_STATUS_OS_NETWORK_CONNECTION_CLOSED) && + (nRetVal != XN_STATUS_OS_NETWORK_TIMEOUT)) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed processing client request: %s", xnGetStatusString(nRetVal)); + } + } + + // We cannot RemoveClient from this thread (as part of it is to close the thread). Instead, signal that + // client has stopped, and let server main thread wait for exit. + m_bHasEnded = TRUE; + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::AddSessionModule(const XnChar* clientName, const XnChar* serverName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream stream; + strcpy(stream.strClientStreamName, clientName); + strcpy(stream.strStreamName, serverName); + stream.bIsOpen = FALSE; + stream.pSession = this; + + nRetVal = m_streamsHash.Set(clientName, stream); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::RemoveSessionModule(const XnChar* clientName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + SessionStream* pStream; + nRetVal = m_streamsHash.Get(clientName, pStream); + if (nRetVal == XN_STATUS_OK) + { + m_streamsHash.Remove(clientName); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::OnPropertyChanged(const XnProperty* pProp) +{ + XnStatus nRetVal = XN_STATUS_OK; + + XnAutoCSLocker streamLocker(m_hStreamsLock); + + SessionStream* pStream = NULL; + nRetVal = FindStreamByServerName(pProp->GetModule(), &pStream); + XN_IS_STATUS_OK(nRetVal); + + // send message + m_pLogger->DumpMessage("PropChange", 0, m_nID, pProp->GetName()); + + XnAutoCSLocker commLocker(m_hCommLock); + switch (pProp->GetType()) + { + case XN_PROPERTY_TYPE_INTEGER: + { + XnActualIntProperty* pActualProp = (XnActualIntProperty*)pProp; + nRetVal = m_privateOutgoingPacker.WriteProperty(pStream->strClientStreamName, pProp->GetName(), pActualProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_REAL: + { + XnActualRealProperty* pActualProp = (XnActualRealProperty*)pProp; + nRetVal = m_privateOutgoingPacker.WriteProperty(pStream->strClientStreamName, pProp->GetName(), pActualProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_STRING: + { + XnActualStringProperty* pActualProp = (XnActualStringProperty*)pProp; + nRetVal = m_privateOutgoingPacker.WriteProperty(pStream->strClientStreamName, pProp->GetName(), pActualProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + case XN_PROPERTY_TYPE_GENERAL: + { + XnActualGeneralProperty* pActualProp = (XnActualGeneralProperty*)pProp; + nRetVal = m_privateOutgoingPacker.WriteProperty(pStream->strClientStreamName, pProp->GetName(), pActualProp->GetValue()); + XN_IS_STATUS_OK(nRetVal); + break; + } + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_SERVER, "Unknown property type: %d", pProp->GetType()); + } + + return (XN_STATUS_OK); +} + +XnStatus XnServerSession::OnNewData(SessionStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // send to client + XnSensorServerNewStreamData message; + xnOSMemSet(&message, 0, sizeof(message)); + message.nTimestamp = nTimestamp; + message.nFrameID = nFrameID; + strcpy(message.strStreamName, pStream->strClientStreamName); + m_pLogger->DumpMessage("NewData", sizeof(XnSensorServerNewStreamData), 0, pStream->strClientStreamName); + + XnAutoCSLocker locker(m_hCommLock); + nRetVal = m_privateOutgoingPacker.WriteCustomData(XN_SENSOR_SERVER_MESSAGE_NEW_STREAM_DATA, &message, sizeof(XnSensorServerNewStreamData)); + if (nRetVal != XN_STATUS_OK) + { + xnLogWarning(XN_MASK_SENSOR_SERVER, "Failed sending new data event to client %d", m_nID); + } + + return (XN_STATUS_OK); +} + +void XN_CALLBACK_TYPE XnServerSession::PropertyChangedCallback(const XnProperty* pProp, void* pCookie) +{ + XnServerSession* pThis = (XnServerSession*)pCookie; + pThis->OnPropertyChanged(pProp); +} + +void XN_CALLBACK_TYPE XnServerSession::StreamNewDataCallback(const XnChar* strName, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie) +{ + SessionStream* pStream = (SessionStream*)pCookie; + pStream->pSession->OnNewData(pStream, nTimestamp, nFrameID); +} + +XN_THREAD_PROC XnServerSession::ServeThreadCallback(XN_THREAD_PARAM pThreadParam) +{ + XnServerSession* pThis = (XnServerSession*)pThreadParam; + XnStatus nRetVal = pThis->ServeThread(); + XN_THREAD_PROC_RETURN(nRetVal); +} + diff --git a/Source/XnDeviceSensorV2/XnServerSession.h b/Source/XnDeviceSensorV2/XnServerSession.h new file mode 100644 index 0000000..69bb10a --- /dev/null +++ b/Source/XnDeviceSensorV2/XnServerSession.h @@ -0,0 +1,138 @@ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ +#ifndef __XN_SERVER_SESSION_H__ +#define __XN_SERVER_SESSION_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSensorsManager.h" +#include +#include +#include "XnSensorClientServer.h" +#include "XnServerLogger.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- + +class XnServerSession +{ +public: + XnServerSession(XnSensorsManager* pSensorsManager, XnUInt32 nID, XN_SOCKET_HANDLE hSocket, XnServerLogger* pLogger); + ~XnServerSession() ; + + XnStatus Init(); + void Free(); + + inline XnUInt32 ID() const { return m_nID; } + inline XnBool HasEnded() const { return m_bHasEnded; } + +private: + // Types + typedef struct + { + XnServerSession* pSession; + XnChar strStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + XnChar strClientStreamName[XN_DEVICE_MAX_STRING_LENGTH]; + XnBool bIsOpen; + XnCallbackHandle hNewDataCallback; + } SessionStream; + + XN_DECLARE_STRINGS_HASH(SessionStream, SessionStreamsHash); + + // Functions + XnStatus SendReply(XnSensorServerCustomMessages Type, XnStatus nRC, XnUInt32 nDataSize = 0, void* pAdditionalData = NULL); + XnStatus SendInitialState(); + XnStatus FindStreamByServerName(const XnChar* strName, SessionStream** ppStream); + + XnStatus HandleOpenSensor(); + XnStatus OpenSensorImpl(const XnChar* strConnectionString); + XnStatus CloseSensorImpl(); + XnStatus HandleSetIntProperty(); + XnStatus SetIntPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnUInt64 nValue); + XnStatus HandleSetRealProperty(); + XnStatus SetRealPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnDouble dValue); + XnStatus HandleSetStringProperty(); + XnStatus SetStringPropertyImpl(const XnChar* strModule, const XnChar* strProp, const XnChar* strValue); + XnStatus HandleSetGeneralProperty(); + XnStatus SetGeneralPropertyImpl(const XnChar* strModule, const XnChar* strProp, const XnGeneralBuffer& gbValue); + XnStatus HandleGetIntProperty(); + XnStatus GetIntPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnUInt64* pnValue); + XnStatus HandleGetRealProperty(); + XnStatus GetRealPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnDouble* pdValue); + XnStatus HandleGetStringProperty(); + XnStatus GetStringPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnChar* strValue); + XnStatus HandleGetGeneralProperty(); + XnStatus GetGeneralPropertyImpl(const XnChar* strModule, const XnChar* strProp, XnGeneralBuffer& gbValue); + XnStatus HandleConfigFromINIFile(); + XnStatus ConfigFromINIFileImpl(const XnChar* strFileName, const XnChar* strSectionName); + XnStatus HandleBatchConfig(); + XnStatus BatchConfigImpl(const XnPropertySet* pProps); + XnStatus HandleNewStream(); + XnStatus NewStreamImpl(const XnChar* strType, const XnChar* strName, const XnPropertySet* pInitialValues); + XnStatus HandleRemoveStream(); + XnStatus RemoveStreamImpl(const XnChar* strName); + XnStatus HandleOpenStream(); + XnStatus OpenStreamImpl(const XnChar* strName); + XnStatus HandleCloseStream(); + XnStatus CloseStreamImpl(const XnChar* strName); + XnStatus HandleReadStream(); + XnStatus ReadStreamImpl(const XnChar* strName, XnSensorServerReadReply* pReply); + XnStatus HandleCloseSession(); + XnStatus CloseSessionImpl(); + + XnStatus HandleSingleRequest(); + + XnStatus AddSessionModule(const XnChar* clientName, const XnChar* serverName); + XnStatus RemoveSessionModule(const XnChar* clientName); + + XnStatus OnPropertyChanged(const XnProperty* pProp); + XnStatus OnNewData(SessionStream* pStream, XnUInt64 nTimestamp, XnUInt32 nFrameID); + + XnStatus ServeThread(); + + static void XN_CALLBACK_TYPE PropertyChangedCallback(const XnProperty* pProp, void* pCookie); + static void XN_CALLBACK_TYPE StreamNewDataCallback(const XnChar* strName, XnUInt64 nTimestamp, XnUInt32 nFrameID, void* pCookie); + static XN_THREAD_PROC ServeThreadCallback(XN_THREAD_PARAM pThreadParam); + + // Members + XnSensorsManager* m_pSensorsManager; + XnUInt32 m_nID; + XN_SOCKET_HANDLE m_hSocket; + XN_THREAD_HANDLE m_hThread; + XN_CRITICAL_SECTION_HANDLE m_hCommLock; + XN_CRITICAL_SECTION_HANDLE m_hStreamsLock; + XnIONetworkStream m_ioStream; + XnDataPacker m_privateIncomingPacker; + XnDataPacker m_privateOutgoingPacker; + XnStreamDataSet* m_pStreamDataSet; + XnBool m_bShouldRun; + XnBool m_bHasEnded; + XnServerSensorInvoker* m_pSensor; + SessionStreamsHash m_streamsHash; + XnServerLogger* m_pLogger; + XnCallbackHandle m_hProprtyChangeCallback; +}; + +#endif // __XN_SERVER_SESSION_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.cpp b/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.cpp index 4e6d432..d412396 100644 --- a/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.cpp +++ b/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.cpp @@ -1,132 +1,132 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnSharedMemoryBufferPool.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnSharedMemoryBufferPool::XnSharedMemoryBufferPool(XnUInt32 nBufferCount, const XnChar* strName, XnUInt32 nMaxBufferSize) : - XnBufferPool(nBufferCount), - m_nMaxBufferSize(nMaxBufferSize), - m_hSharedMemory(NULL), - m_pSharedMemoryAddress(NULL) -{ - // to make the name unique, we'll add process ID - XN_PROCESS_ID procID; - xnOSGetCurrentProcessID(&procID); - sprintf(m_strName, "%u_%s", procID, strName); -} - -XnSharedMemoryBufferPool::~XnSharedMemoryBufferPool() -{ - XnSharedMemoryBufferPool::Free(); -} - -XnStatus XnSharedMemoryBufferPool::AllocateBuffers() -{ - XnStatus nRetVal = XN_STATUS_OK; - - if (m_nBufferSize > m_nMaxBufferSize) - { - return XN_STATUS_ALLOC_FAILED; - } - - if (m_pSharedMemoryAddress != NULL) - { - // already allocated. nothing to do here - return (XN_STATUS_OK); - } - - // first time. allocate shared memory - XnUInt32 nTotalSize = m_nMaxBufferSize * m_nBufferCount; - nRetVal = xnOSCreateSharedMemory(m_strName, nTotalSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory); - XN_IS_STATUS_OK(nRetVal); - - void* pAddress; - nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, &pAddress); - if (nRetVal != XN_STATUS_OK) - { - xnOSCloseSharedMemory(m_hSharedMemory); - m_hSharedMemory = NULL; - return (nRetVal); - } - - m_pSharedMemoryAddress = (XnUChar*)pAddress; - - // now allocate buffers - for (XnUInt32 i = 0; i < m_nBufferCount; ++i) - { - XnBufferInPool* pBuffer = XN_NEW(XnBufferInPool); - if (pBuffer == NULL) - { - Free(); - return (XN_STATUS_ALLOC_FAILED); - } - - pBuffer->m_nID = i; - - pBuffer->SetExternalBuffer(m_pSharedMemoryAddress + i*m_nMaxBufferSize, m_nMaxBufferSize); - - xnDumpWriteString(Dump(), "Allocated buffer %u with size %u\n", i, m_nMaxBufferSize); - - // add it to free list - m_AllBuffers.AddLast(pBuffer); - m_FreeBuffers.AddLast(pBuffer); - } - - return (XN_STATUS_OK); -} - -void XnSharedMemoryBufferPool::DestroyBuffer(XnBufferInPool* pBuffer) -{ - // simply add it back to free list - m_FreeBuffers.AddLast(pBuffer); -} - -void XnSharedMemoryBufferPool::Free() -{ - if (m_hSharedMemory != NULL) - { - xnOSCloseSharedMemory(m_hSharedMemory); - m_hSharedMemory = NULL; - } - - for (XnBuffersList::Iterator it = m_AllBuffers.begin(); it != m_AllBuffers.end(); ++it) - { - XnBufferInPool* pBuffer = *it; - XN_DELETE(pBuffer); - } - - m_AllBuffers.Clear(); - m_FreeBuffers.Clear(); - XnBufferPool::Free(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnSharedMemoryBufferPool.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnSharedMemoryBufferPool::XnSharedMemoryBufferPool(XnUInt32 nBufferCount, const XnChar* strDeviceName, const XnChar* strStreamName, XnUInt32 nMaxBufferSize) : + XnBufferPool(nBufferCount), + m_nMaxBufferSize(nMaxBufferSize), + m_hSharedMemory(NULL), + m_pSharedMemoryAddress(NULL) +{ + // to make the name unique, we'll add process ID + XN_PROCESS_ID procID; + xnOSGetCurrentProcessID(&procID); + sprintf(m_strName, "%u_%s_%s", procID, strDeviceName, strStreamName); +} + +XnSharedMemoryBufferPool::~XnSharedMemoryBufferPool() +{ + XnSharedMemoryBufferPool::Free(); +} + +XnStatus XnSharedMemoryBufferPool::AllocateBuffers() +{ + XnStatus nRetVal = XN_STATUS_OK; + + if (m_nBufferSize > m_nMaxBufferSize) + { + return XN_STATUS_ALLOC_FAILED; + } + + if (m_pSharedMemoryAddress != NULL) + { + // already allocated. nothing to do here + return (XN_STATUS_OK); + } + + // first time. allocate shared memory + XnUInt32 nTotalSize = m_nMaxBufferSize * m_nBufferCount; + nRetVal = xnOSCreateSharedMemory(m_strName, nTotalSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory); + XN_IS_STATUS_OK(nRetVal); + + void* pAddress; + nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, &pAddress); + if (nRetVal != XN_STATUS_OK) + { + xnOSCloseSharedMemory(m_hSharedMemory); + m_hSharedMemory = NULL; + return (nRetVal); + } + + m_pSharedMemoryAddress = (XnUChar*)pAddress; + + // now allocate buffers + for (XnUInt32 i = 0; i < m_nBufferCount; ++i) + { + XnBufferInPool* pBuffer = XN_NEW(XnBufferInPool); + if (pBuffer == NULL) + { + Free(); + return (XN_STATUS_ALLOC_FAILED); + } + + pBuffer->m_nID = i; + + pBuffer->SetExternalBuffer(m_pSharedMemoryAddress + i*m_nMaxBufferSize, m_nMaxBufferSize); + + xnDumpWriteString(Dump(), "Allocated buffer %u with size %u\n", i, m_nMaxBufferSize); + + // add it to free list + m_AllBuffers.AddLast(pBuffer); + m_FreeBuffers.AddLast(pBuffer); + } + + return (XN_STATUS_OK); +} + +void XnSharedMemoryBufferPool::DestroyBuffer(XnBufferInPool* pBuffer) +{ + // simply add it back to free list + m_FreeBuffers.AddLast(pBuffer); +} + +void XnSharedMemoryBufferPool::Free() +{ + if (m_hSharedMemory != NULL) + { + xnOSCloseSharedMemory(m_hSharedMemory); + m_hSharedMemory = NULL; + } + + for (XnBuffersList::Iterator it = m_AllBuffers.begin(); it != m_AllBuffers.end(); ++it) + { + XnBufferInPool* pBuffer = *it; + XN_DELETE(pBuffer); + } + + m_AllBuffers.Clear(); + m_FreeBuffers.Clear(); + XnBufferPool::Free(); +} diff --git a/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.h b/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.h index 43b27ba..23cd291 100644 --- a/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.h +++ b/Source/XnDeviceSensorV2/XnSharedMemoryBufferPool.h @@ -1,62 +1,62 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_SHARED_MEMORY_BUFFER_POOL_H__ -#define __XN_SHARED_MEMORY_BUFFER_POOL_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XnSharedMemoryBufferPool : public XnBufferPool -{ -public: - XnSharedMemoryBufferPool(XnUInt32 nBufferCount, const XnChar* strName, XnUInt32 nMaxBufferSize); - ~XnSharedMemoryBufferPool(); - - void Free(); - - inline const XnChar* GetSharedMemoryName() const { return m_strName; } - - inline XnUInt32 GetBufferOffset(XnBuffer* pBuffer) const { return ((XnUChar*)pBuffer->GetData() - m_pSharedMemoryAddress); } - -protected: - virtual XnStatus AllocateBuffers(); - virtual void DestroyBuffer(XnBufferInPool* pBuffer); - -private: - XnChar m_strName[XN_FILE_MAX_PATH]; - XnUInt32 m_nMaxBufferSize; - XN_SHARED_MEMORY_HANDLE m_hSharedMemory; - XnUChar* m_pSharedMemoryAddress; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_SHARED_MEMORY_BUFFER_POOL_H__ +#define __XN_SHARED_MEMORY_BUFFER_POOL_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XnSharedMemoryBufferPool : public XnBufferPool +{ +public: + XnSharedMemoryBufferPool(XnUInt32 nBufferCount, const XnChar* strDeviceName, const XnChar* strStreamName, XnUInt32 nMaxBufferSize); + ~XnSharedMemoryBufferPool(); + + void Free(); + + inline const XnChar* GetSharedMemoryName() const { return m_strName; } + + inline XnUInt32 GetBufferOffset(XnBuffer* pBuffer) const { return ((XnUChar*)pBuffer->GetData() - m_pSharedMemoryAddress); } + +protected: + virtual XnStatus AllocateBuffers(); + virtual void DestroyBuffer(XnBufferInPool* pBuffer); + +private: + XnChar m_strName[XN_FILE_MAX_PATH]; + XnUInt32 m_nMaxBufferSize; + XN_SHARED_MEMORY_HANDLE m_hSharedMemory; + XnUChar* m_pSharedMemoryAddress; +}; + #endif // __XN_SHARED_MEMORY_BUFFER_POOL_H__ \ No newline at end of file diff --git a/Source/XnDeviceSensorV2/XnStreamProcessor.cpp b/Source/XnDeviceSensorV2/XnStreamProcessor.cpp index 91e68fc..6f17056 100644 --- a/Source/XnDeviceSensorV2/XnStreamProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnStreamProcessor.cpp @@ -1,45 +1,45 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamProcessor.h" -#include -#include "XnSensor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStreamProcessor::XnStreamProcessor(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper) : - XnDataProcessor(pHelper->GetPrivateData(), pStream->GetType()), - m_pStream(pStream), - m_pHelper(pHelper) -{ -} - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamProcessor.h" +#include +#include "XnSensor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStreamProcessor::XnStreamProcessor(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper) : + XnDataProcessor(pHelper->GetPrivateData(), pStream->GetType()), + m_pStream(pStream), + m_pHelper(pHelper) +{ +} + + diff --git a/Source/XnDeviceSensorV2/XnStreamProcessor.h b/Source/XnDeviceSensorV2/XnStreamProcessor.h index 7423299..c40b7a2 100644 --- a/Source/XnDeviceSensorV2/XnStreamProcessor.h +++ b/Source/XnDeviceSensorV2/XnStreamProcessor.h @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_STREAM_PROCESSOR_H__ -#define __XN_STREAM_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessor.h" -#include "XnSensorStreamHelper.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -/** -* Base class for streams data processors -*/ -class XnStreamProcessor : public XnDataProcessor -{ -public: - XnStreamProcessor(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper); - -//--------------------------------------------------------------------------- -// Utility Functions -//--------------------------------------------------------------------------- -protected: - XnDeviceStream* GetStream() { return m_pStream; } - XnSensorStreamHelper* GetStreamHelper() { return m_pHelper; } - -//--------------------------------------------------------------------------- -// Members -//--------------------------------------------------------------------------- -private: - XnDeviceStream* m_pStream; - XnSensorStreamHelper* m_pHelper; -}; - -#endif //__XN_STREAM_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_STREAM_PROCESSOR_H__ +#define __XN_STREAM_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessor.h" +#include "XnSensorStreamHelper.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +/** +* Base class for streams data processors +*/ +class XnStreamProcessor : public XnDataProcessor +{ +public: + XnStreamProcessor(XnDeviceStream* pStream, XnSensorStreamHelper* pHelper); + +//--------------------------------------------------------------------------- +// Utility Functions +//--------------------------------------------------------------------------- +protected: + XnDeviceStream* GetStream() { return m_pStream; } + XnSensorStreamHelper* GetStreamHelper() { return m_pHelper; } + +//--------------------------------------------------------------------------- +// Members +//--------------------------------------------------------------------------- +private: + XnDeviceStream* m_pStream; + XnSensorStreamHelper* m_pHelper; +}; + +#endif //__XN_STREAM_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.cpp b/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.cpp index 326daee..8b6d5ad 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.cpp @@ -1,108 +1,108 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnUncompressedBayerProcessor.h" -#include "Uncomp.h" -#include "Bayer.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnUncompressedBayerProcessor::XnUncompressedBayerProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnUncompressedBayerProcessor::~XnUncompressedBayerProcessor() -{ -} - -XnStatus XnUncompressedBayerProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnImageProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - break; - case XN_OUTPUT_FORMAT_RGB24: - XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedBayerBuffer, GetExpectedOutputSize()); - break; - default: - XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); - } - - return (XN_STATUS_OK); -} - -void XnUncompressedBayerProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnUncompressedBayerProcessor::ProcessFramePacketChunk") - - // if output format is Gray8, we can write directly to output buffer. otherwise, we need - // to write to a temp buffer. - XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE8) ? GetWriteBuffer() : &m_UncompressedBayerBuffer; - - // make sure we have enough room - if (CheckWriteBufferForOverflow(nDataSize)) - { - pWriteBuffer->UnsafeWrite(pData, nDataSize); - } - - XN_PROFILING_END_SECTION -} - -void XnUncompressedBayerProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XN_PROFILING_START_SECTION("XnUncompressedBayerProcessor::OnEndOfFrame") - - // if data was written to temp buffer, convert it now - switch (GetStream()->GetOutputFormat()) - { - case XN_OUTPUT_FORMAT_GRAYSCALE8: - break; - case XN_OUTPUT_FORMAT_RGB24: - { - Bayer2RGB888(m_UncompressedBayerBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), GetActualXRes(), GetActualYRes(), 1, 0); - GetWriteBuffer()->UnsafeUpdateSize(GetActualXRes()*GetActualYRes()*3); - m_UncompressedBayerBuffer.Reset(); - } - break; - } - - XnImageProcessor::OnEndOfFrame(pHeader); - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnUncompressedBayerProcessor.h" +#include "Uncomp.h" +#include "Bayer.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnUncompressedBayerProcessor::XnUncompressedBayerProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnUncompressedBayerProcessor::~XnUncompressedBayerProcessor() +{ +} + +XnStatus XnUncompressedBayerProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnImageProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + break; + case XN_OUTPUT_FORMAT_RGB24: + XN_VALIDATE_BUFFER_ALLOCATE(m_UncompressedBayerBuffer, GetExpectedOutputSize()); + break; + default: + XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_SENSOR_PROTOCOL_IMAGE, "Unsupported image output format: %d", GetStream()->GetOutputFormat()); + } + + return (XN_STATUS_OK); +} + +void XnUncompressedBayerProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnUncompressedBayerProcessor::ProcessFramePacketChunk") + + // if output format is Gray8, we can write directly to output buffer. otherwise, we need + // to write to a temp buffer. + XnBuffer* pWriteBuffer = (GetStream()->GetOutputFormat() == XN_OUTPUT_FORMAT_GRAYSCALE8) ? GetWriteBuffer() : &m_UncompressedBayerBuffer; + + // make sure we have enough room + if (CheckWriteBufferForOverflow(nDataSize)) + { + pWriteBuffer->UnsafeWrite(pData, nDataSize); + } + + XN_PROFILING_END_SECTION +} + +void XnUncompressedBayerProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XN_PROFILING_START_SECTION("XnUncompressedBayerProcessor::OnEndOfFrame") + + // if data was written to temp buffer, convert it now + switch (GetStream()->GetOutputFormat()) + { + case XN_OUTPUT_FORMAT_GRAYSCALE8: + break; + case XN_OUTPUT_FORMAT_RGB24: + { + Bayer2RGB888(m_UncompressedBayerBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), GetActualXRes(), GetActualYRes(), 1, 0); + GetWriteBuffer()->UnsafeUpdateSize(GetActualXRes()*GetActualYRes()*3); + m_UncompressedBayerBuffer.Reset(); + } + break; + } + + XnImageProcessor::OnEndOfFrame(pHeader); + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.h b/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.h index 4227186..359caf8 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.h +++ b/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.h @@ -1,61 +1,61 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ -#define __XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnUncompressedBayerProcessor : public XnImageProcessor -{ -public: - XnUncompressedBayerProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnUncompressedBayerProcessor(); - - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - - //--------------------------------------------------------------------------- - // Class Members - //--------------------------------------------------------------------------- -private: - XnBuffer m_UncompressedBayerBuffer; -}; - -#endif //__XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ +#define __XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnUncompressedBayerProcessor : public XnImageProcessor +{ +public: + XnUncompressedBayerProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnUncompressedBayerProcessor(); + + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + + //--------------------------------------------------------------------------- + // Class Members + //--------------------------------------------------------------------------- +private: + XnBuffer m_UncompressedBayerBuffer; +}; + +#endif //__XN_UNCOMPRESSED_BAYER_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.cpp b/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.cpp index faf8bfd..88f6d5e 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.cpp @@ -1,81 +1,81 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnUncompressedDepthProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnUncompressedDepthProcessor::XnUncompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : - XnDepthProcessor(pStream, pHelper) -{ -} - -XnUncompressedDepthProcessor::~XnUncompressedDepthProcessor() -{ -} - -void XnUncompressedDepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnUncompressedDepthProcessor::ProcessFramePacketChunk") - - // when depth is uncompressed, we can just copy it directly to write buffer - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - // make sure we have enough room - if (CheckWriteBufferForOverflow(nDataSize)) - { - // sometimes, when packets are lost, we get uneven number of bytes, so we need to complete - // one byte, in order to keep UINT16 alignment - if (nDataSize % 2 != 0) - { - nDataSize--; - pData++; - } - - // copy values. Make sure we do not get corrupted shifts - XnUInt16* pRaw = (XnUInt16*)(pData); - XnUInt16* pRawEnd = (XnUInt16*)(pData + nDataSize); - XnDepthPixel* pWriteBuf = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); - - while (pRaw < pRawEnd) - { - *pWriteBuf = GetOutput(XN_MIN(*pRaw, XN_DEVICE_SENSOR_MAX_SHIFT_VALUE-1)); - ++pRaw; - ++pWriteBuf; - } - - pWriteBuffer->UnsafeUpdateSize(nDataSize); - } - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnUncompressedDepthProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnUncompressedDepthProcessor::XnUncompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper) : + XnDepthProcessor(pStream, pHelper) +{ +} + +XnUncompressedDepthProcessor::~XnUncompressedDepthProcessor() +{ +} + +void XnUncompressedDepthProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnUncompressedDepthProcessor::ProcessFramePacketChunk") + + // when depth is uncompressed, we can just copy it directly to write buffer + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + // make sure we have enough room + if (CheckWriteBufferForOverflow(nDataSize)) + { + // sometimes, when packets are lost, we get uneven number of bytes, so we need to complete + // one byte, in order to keep UINT16 alignment + if (nDataSize % 2 != 0) + { + nDataSize--; + pData++; + } + + // copy values. Make sure we do not get corrupted shifts + XnUInt16* pRaw = (XnUInt16*)(pData); + XnUInt16* pRawEnd = (XnUInt16*)(pData + nDataSize); + XnDepthPixel* pWriteBuf = (XnDepthPixel*)pWriteBuffer->GetUnsafeWritePointer(); + + while (pRaw < pRawEnd) + { + *pWriteBuf = GetOutput(XN_MIN(*pRaw, XN_DEVICE_SENSOR_MAX_SHIFT_VALUE-1)); + ++pRaw; + ++pWriteBuf; + } + + pWriteBuffer->UnsafeUpdateSize(nDataSize); + } + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.h b/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.h index d5f52eb..8cafa8e 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.h +++ b/Source/XnDeviceSensorV2/XnUncompressedDepthProcessor.h @@ -1,52 +1,52 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ -#define __XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDepthProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnUncompressedDepthProcessor : public XnDepthProcessor -{ -public: - XnUncompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); - virtual ~XnUncompressedDepthProcessor(); - -protected: - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); -}; - -#endif //__XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ +#define __XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDepthProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnUncompressedDepthProcessor : public XnDepthProcessor +{ +public: + XnUncompressedDepthProcessor(XnSensorDepthStream* pStream, XnSensorStreamHelper* pHelper); + virtual ~XnUncompressedDepthProcessor(); + +protected: + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); +}; + +#endif //__XN_UNCOMPRESSED_DEPTH_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.cpp b/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.cpp index aa61ef4..ab833e1 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.cpp @@ -1,61 +1,61 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnUncompressedYUVImageProcessor.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnUncompressedYUVImageProcessor::XnUncompressedYUVImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnUncompressedYUVImageProcessor::~XnUncompressedYUVImageProcessor() -{ -} - -void XnUncompressedYUVImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnUncompressedYUVImageProcessor::ProcessFramePacketChunk") - - // when image is uncompressed, we can just copy it directly to write buffer - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - // make sure we have enough room - if (CheckWriteBufferForOverflow(nDataSize)) - { - pWriteBuffer->UnsafeWrite(pData, nDataSize); - } - - XN_PROFILING_END_SECTION -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnUncompressedYUVImageProcessor.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnUncompressedYUVImageProcessor::XnUncompressedYUVImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnUncompressedYUVImageProcessor::~XnUncompressedYUVImageProcessor() +{ +} + +void XnUncompressedYUVImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnUncompressedYUVImageProcessor::ProcessFramePacketChunk") + + // when image is uncompressed, we can just copy it directly to write buffer + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + // make sure we have enough room + if (CheckWriteBufferForOverflow(nDataSize)) + { + pWriteBuffer->UnsafeWrite(pData, nDataSize); + } + + XN_PROFILING_END_SECTION +} diff --git a/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.h b/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.h index 7b95d48..78eae22 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnUncompressedYUVImageProcessor.h @@ -1,52 +1,52 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ -#define __XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnUncompressedYUVImageProcessor : public XnImageProcessor -{ -public: - XnUncompressedYUVImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnUncompressedYUVImageProcessor(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); -}; - -#endif //__XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ +#define __XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnUncompressedYUVImageProcessor : public XnImageProcessor +{ +public: + XnUncompressedYUVImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnUncompressedYUVImageProcessor(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); +}; + +#endif //__XN_UNCOMPRESSED_YUV_IMAGE_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.cpp b/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.cpp index aa485e7..50ac0da 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.cpp @@ -1,120 +1,120 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnUncompressedYUVtoRGBImageProcessor.h" -#include "YUV.h" -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -XnUncompressedYUVtoRGBImageProcessor::XnUncompressedYUVtoRGBImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : - XnImageProcessor(pStream, pHelper) -{ -} - -XnUncompressedYUVtoRGBImageProcessor::~XnUncompressedYUVtoRGBImageProcessor() -{ -} - -XnStatus XnUncompressedYUVtoRGBImageProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnImageProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE) - - return (XN_STATUS_OK); -} - -void XnUncompressedYUVtoRGBImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - XN_PROFILING_START_SECTION("XnUncompressedYUVtoRGBImageProcessor::ProcessFramePacketChunk") - - XnBuffer* pWriteBuffer = GetWriteBuffer(); - - if (m_ContinuousBuffer.GetSize() != 0) - { - // fill in to a whole element - XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); - m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); - pData += nReadBytes; - nDataSize -= nReadBytes; - - if (m_ContinuousBuffer.GetSize() == XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE) - { - if (CheckWriteBufferForOverflow(XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE)) - { - // process it - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - YUV422ToRGB888(m_ContinuousBuffer.GetData(), pWriteBuffer->GetUnsafeWritePointer(), XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE, &nActualRead, &nOutputSize); - pWriteBuffer->UnsafeUpdateSize(XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE); - } - - m_ContinuousBuffer.Reset(); - } - } - - if (CheckWriteBufferForOverflow(nDataSize / XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE * XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE)) - { - XnUInt32 nActualRead = 0; - XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); - YUV422ToRGB888(pData, pWriteBuffer->GetUnsafeWritePointer(), nDataSize, &nActualRead, &nOutputSize); - pWriteBuffer->UnsafeUpdateSize(nOutputSize); - pData += nActualRead; - nDataSize -= nActualRead; - - // if we have any bytes left, store them for next packet. - if (nDataSize > 0) - { - // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE - // are left. - m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); - } - } - - XN_PROFILING_END_SECTION -} - -void XnUncompressedYUVtoRGBImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnImageProcessor::OnStartOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} - -void XnUncompressedYUVtoRGBImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) -{ - XnImageProcessor::OnEndOfFrame(pHeader); - m_ContinuousBuffer.Reset(); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnUncompressedYUVtoRGBImageProcessor.h" +#include "YUV.h" +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +XnUncompressedYUVtoRGBImageProcessor::XnUncompressedYUVtoRGBImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper) : + XnImageProcessor(pStream, pHelper) +{ +} + +XnUncompressedYUVtoRGBImageProcessor::~XnUncompressedYUVtoRGBImageProcessor() +{ +} + +XnStatus XnUncompressedYUVtoRGBImageProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnImageProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + XN_VALIDATE_BUFFER_ALLOCATE(m_ContinuousBuffer, XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE) + + return (XN_STATUS_OK); +} + +void XnUncompressedYUVtoRGBImageProcessor::ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + XN_PROFILING_START_SECTION("XnUncompressedYUVtoRGBImageProcessor::ProcessFramePacketChunk") + + XnBuffer* pWriteBuffer = GetWriteBuffer(); + + if (m_ContinuousBuffer.GetSize() != 0) + { + // fill in to a whole element + XnUInt32 nReadBytes = XN_MIN(nDataSize, XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE - m_ContinuousBuffer.GetSize()); + m_ContinuousBuffer.UnsafeWrite(pData, nReadBytes); + pData += nReadBytes; + nDataSize -= nReadBytes; + + if (m_ContinuousBuffer.GetSize() == XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE) + { + if (CheckWriteBufferForOverflow(XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE)) + { + // process it + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + YUV422ToRGB888(m_ContinuousBuffer.GetData(), pWriteBuffer->GetUnsafeWritePointer(), XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE, &nActualRead, &nOutputSize); + pWriteBuffer->UnsafeUpdateSize(XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE); + } + + m_ContinuousBuffer.Reset(); + } + } + + if (CheckWriteBufferForOverflow(nDataSize / XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE * XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE)) + { + XnUInt32 nActualRead = 0; + XnUInt32 nOutputSize = pWriteBuffer->GetFreeSpaceInBuffer(); + YUV422ToRGB888(pData, pWriteBuffer->GetUnsafeWritePointer(), nDataSize, &nActualRead, &nOutputSize); + pWriteBuffer->UnsafeUpdateSize(nOutputSize); + pData += nActualRead; + nDataSize -= nActualRead; + + // if we have any bytes left, store them for next packet. + if (nDataSize > 0) + { + // no need to check for overflow. there can not be a case in which more than XN_INPUT_ELEMENT_SIZE + // are left. + m_ContinuousBuffer.UnsafeWrite(pData, nDataSize); + } + } + + XN_PROFILING_END_SECTION +} + +void XnUncompressedYUVtoRGBImageProcessor::OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnImageProcessor::OnStartOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} + +void XnUncompressedYUVtoRGBImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) +{ + XnImageProcessor::OnEndOfFrame(pHeader); + m_ContinuousBuffer.Reset(); +} diff --git a/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.h b/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.h index 5412b91..34c94bc 100644 --- a/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.h +++ b/Source/XnDeviceSensorV2/XnUncompressedYUVtoRGBImageProcessor.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ -#define __XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnImageProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- - -class XnUncompressedYUVtoRGBImageProcessor : public XnImageProcessor -{ -public: - XnUncompressedYUVtoRGBImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); - ~XnUncompressedYUVtoRGBImageProcessor(); - - XnStatus Init(); - - //--------------------------------------------------------------------------- - // Overridden Functions - //--------------------------------------------------------------------------- -protected: - virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); - virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); - -private: - XnBuffer m_ContinuousBuffer; -}; - -#endif //__XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ +#define __XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnImageProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- + +class XnUncompressedYUVtoRGBImageProcessor : public XnImageProcessor +{ +public: + XnUncompressedYUVtoRGBImageProcessor(XnSensorImageStream* pStream, XnSensorStreamHelper* pHelper); + ~XnUncompressedYUVtoRGBImageProcessor(); + + XnStatus Init(); + + //--------------------------------------------------------------------------- + // Overridden Functions + //--------------------------------------------------------------------------- +protected: + virtual void ProcessFramePacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + virtual void OnStartOfFrame(const XnSensorProtocolResponseHeader* pHeader); + virtual void OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader); + +private: + XnBuffer m_ContinuousBuffer; +}; + +#endif //__XN_UNCOMPRESSED_YUV_TO_RGB_IMAGE_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/XnWholePacketProcessor.cpp b/Source/XnDeviceSensorV2/XnWholePacketProcessor.cpp index f44b8dc..2995369 100644 --- a/Source/XnDeviceSensorV2/XnWholePacketProcessor.cpp +++ b/Source/XnDeviceSensorV2/XnWholePacketProcessor.cpp @@ -1,84 +1,84 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnWholePacketProcessor.h" - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnWholePacketProcessor::XnWholePacketProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName, XnUInt32 nMaxPacketSize) : - XnDataProcessor(pDevicePrivateData, csName), - m_nMaxPacketSize(nMaxPacketSize) -{} - -XnWholePacketProcessor::~XnWholePacketProcessor() -{} - -XnStatus XnWholePacketProcessor::Init() -{ - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnDataProcessor::Init(); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = m_WholePacket.Allocate(m_nMaxPacketSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); -} - -void XnWholePacketProcessor::ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) -{ - if (nDataOffset == 0 && m_WholePacket.GetSize() != 0) - { - // previous packet was not received to its end - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s: Expected %d additional bytes in packet (got %d out of %d bytes)!", m_csName, pHeader->nBufSize - m_WholePacket.GetSize(), m_WholePacket.GetSize(), pHeader->nBufSize); - m_WholePacket.Reset(); - } - - // sanity check - if (pHeader->nBufSize > m_WholePacket.GetMaxSize()) - { - xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Got a packet which is bigger than max size! (%d > %d)", pHeader->nBufSize, m_WholePacket.GetMaxSize()); - } - else - { - // append data - m_WholePacket.UnsafeWrite(pData, nDataSize); - - // check if we have entire packet - if (m_WholePacket.GetSize() == pHeader->nBufSize) - { - // process it - ProcessWholePacket(pHeader, m_WholePacket.GetData()); - m_WholePacket.Reset(); - } - } -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnWholePacketProcessor.h" + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnWholePacketProcessor::XnWholePacketProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName, XnUInt32 nMaxPacketSize) : + XnDataProcessor(pDevicePrivateData, csName), + m_nMaxPacketSize(nMaxPacketSize) +{} + +XnWholePacketProcessor::~XnWholePacketProcessor() +{} + +XnStatus XnWholePacketProcessor::Init() +{ + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnDataProcessor::Init(); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = m_WholePacket.Allocate(m_nMaxPacketSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); +} + +void XnWholePacketProcessor::ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize) +{ + if (nDataOffset == 0 && m_WholePacket.GetSize() != 0) + { + // previous packet was not received to its end + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "%s: Expected %d additional bytes in packet (got %d out of %d bytes)!", m_csName, pHeader->nBufSize - m_WholePacket.GetSize(), m_WholePacket.GetSize(), pHeader->nBufSize); + m_WholePacket.Reset(); + } + + // sanity check + if (pHeader->nBufSize > m_WholePacket.GetMaxSize()) + { + xnLogWarning(XN_MASK_SENSOR_PROTOCOL, "Got a packet which is bigger than max size! (%d > %d)", pHeader->nBufSize, m_WholePacket.GetMaxSize()); + } + else + { + // append data + m_WholePacket.UnsafeWrite(pData, nDataSize); + + // check if we have entire packet + if (m_WholePacket.GetSize() == pHeader->nBufSize) + { + // process it + ProcessWholePacket(pHeader, m_WholePacket.GetData()); + m_WholePacket.Reset(); + } + } +} diff --git a/Source/XnDeviceSensorV2/XnWholePacketProcessor.h b/Source/XnDeviceSensorV2/XnWholePacketProcessor.h index 24dbfbf..114c1f3 100644 --- a/Source/XnDeviceSensorV2/XnWholePacketProcessor.h +++ b/Source/XnDeviceSensorV2/XnWholePacketProcessor.h @@ -1,65 +1,65 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_WHOLE_PACKET_PROCESSOR_H__ -#define __XN_WHOLE_PACKET_PROCESSOR_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDataProcessor.h" - -//--------------------------------------------------------------------------- -// XnWholePacketProcessor Class -//--------------------------------------------------------------------------- -class XnWholePacketProcessor : public XnDataProcessor -{ -public: - XnWholePacketProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName, XnUInt32 nMaxPacketSize); - ~XnWholePacketProcessor(); - - XnStatus Init(); - -//--------------------------------------------------------------------------- -// Overridden Functions -//--------------------------------------------------------------------------- -protected: - void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); - -//--------------------------------------------------------------------------- -// Virtual Functions -//--------------------------------------------------------------------------- -protected: - virtual void ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData) = 0; - -private: - /* The maximum size of the packet. */ - XnUInt32 m_nMaxPacketSize; - /* A buffer to store whole packet */ - XnBuffer m_WholePacket; -}; - -#endif //__XN_WHOLE_PACKET_PROCESSOR_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_WHOLE_PACKET_PROCESSOR_H__ +#define __XN_WHOLE_PACKET_PROCESSOR_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDataProcessor.h" + +//--------------------------------------------------------------------------- +// XnWholePacketProcessor Class +//--------------------------------------------------------------------------- +class XnWholePacketProcessor : public XnDataProcessor +{ +public: + XnWholePacketProcessor(XnDevicePrivateData* pDevicePrivateData, const XnChar* csName, XnUInt32 nMaxPacketSize); + ~XnWholePacketProcessor(); + + XnStatus Init(); + +//--------------------------------------------------------------------------- +// Overridden Functions +//--------------------------------------------------------------------------- +protected: + void ProcessPacketChunk(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData, XnUInt32 nDataOffset, XnUInt32 nDataSize); + +//--------------------------------------------------------------------------- +// Virtual Functions +//--------------------------------------------------------------------------- +protected: + virtual void ProcessWholePacket(const XnSensorProtocolResponseHeader* pHeader, const XnUChar* pData) = 0; + +private: + /* The maximum size of the packet. */ + XnUInt32 m_nMaxPacketSize; + /* A buffer to store whole packet */ + XnBuffer m_WholePacket; +}; + +#endif //__XN_WHOLE_PACKET_PROCESSOR_H__ diff --git a/Source/XnDeviceSensorV2/YUV.cpp b/Source/XnDeviceSensorV2/YUV.cpp index 6eeb605..7a20c9b 100644 --- a/Source/XnDeviceSensorV2/YUV.cpp +++ b/Source/XnDeviceSensorV2/YUV.cpp @@ -1,230 +1,230 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "YUV.h" -#include - -#if (XN_PLATFORM == XN_PLATFORM_WIN32) - #ifdef __INTEL_COMPILER - #include - #else - #include - #endif -#endif - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -void YUV444ToRGB888(XnUInt8 cY, XnUInt8 cU, XnUInt8 cV, - XnUInt8& cR, XnUInt8& cG, XnUInt8& cB) -{ - XnInt32 nC = cY - 16; - XnInt16 nD = cU - 128; - XnInt16 nE = cV - 128; - - nC = nC * 298 + 128; - - cR = XN_MIN(XN_MAX((nC + 409 * nE) >> 8, 0), 255); - cG = XN_MIN(XN_MAX((nC - 100 * nD - 208 * nE) >> 8, 0), 255); - cB = XN_MIN(XN_MAX((nC + 516 * nD ) >> 8, 0), 255); -} - -#if (XN_PLATFORM == XN_PLATFORM_WIN32) - -void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize) -{ - const XnUInt8* pYUVLast = pYUVImage + nYUVSize - 8; - const XnUInt8* pYUVOrig = pYUVImage; - const XnUInt8* pRGBOrig = pRGBImage; - const XnUInt8* pRGBLast = pRGBImage + *pnRGBSize - 12; - - const __m128 minus16 = _mm_set_ps1(-16); - const __m128 minus128 = _mm_set_ps1(-128); - const __m128 plus113983 = _mm_set_ps1(1.13983F); - const __m128 minus039466 = _mm_set_ps1(-0.39466F); - const __m128 minus058060 = _mm_set_ps1(-0.58060F); - const __m128 plus203211 = _mm_set_ps1(2.03211F); - const __m128 zero = _mm_set_ps1(0); - const __m128 plus255 = _mm_set_ps1(255); - - // define YUV floats - __m128 y; - __m128 u; - __m128 v; - - __m128 temp; - - // define RGB floats - __m128 r; - __m128 g; - __m128 b; - - // define RGB integers - __m128i iR; - __m128i iG; - __m128i iB; - - XnUInt32* piR = (XnUInt32*)&iR; - XnUInt32* piG = (XnUInt32*)&iG; - XnUInt32* piB = (XnUInt32*)&iB; - - while (pYUVImage <= pYUVLast && pRGBImage <= pRGBLast) - { - // process 4 pixels at once (values should be ordered backwards) - y = _mm_set_ps(pYUVImage[YUV422_Y2 + YUV422_BPP], pYUVImage[YUV422_Y1 + YUV422_BPP], pYUVImage[YUV422_Y2], pYUVImage[YUV422_Y1]); - u = _mm_set_ps(pYUVImage[YUV422_U + YUV422_BPP], pYUVImage[YUV422_U + YUV422_BPP], pYUVImage[YUV422_U], pYUVImage[YUV422_U]); - v = _mm_set_ps(pYUVImage[YUV422_V + YUV422_BPP], pYUVImage[YUV422_V + YUV422_BPP], pYUVImage[YUV422_V], pYUVImage[YUV422_V]); - - u = _mm_add_ps(u, minus128); // u -= 128 - v = _mm_add_ps(v, minus128); // v -= 128 - - /* - - http://en.wikipedia.org/wiki/YUV - - From YUV to RGB: - R = Y + 1.13983 V - G = Y - 0.39466 U - 0.58060 V - B = Y + 2.03211 U - - */ - - temp = _mm_mul_ps(plus113983, v); - r = _mm_add_ps(y, temp); - - temp = _mm_mul_ps(minus039466, u); - g = _mm_add_ps(y, temp); - temp = _mm_mul_ps(minus058060, v); - g = _mm_add_ps(g, temp); - - temp = _mm_mul_ps(plus203211, u); - b = _mm_add_ps(y, temp); - - // make sure no value is smaller than 0 - r = _mm_max_ps(r, zero); - g = _mm_max_ps(g, zero); - b = _mm_max_ps(b, zero); - - // make sure no value is bigger than 255 - r = _mm_min_ps(r, plus255); - g = _mm_min_ps(g, plus255); - b = _mm_min_ps(b, plus255); - - // convert floats to int16 (there is no conversion to uint8, just to int8). - iR = _mm_cvtps_epi32(r); - iG = _mm_cvtps_epi32(g); - iB = _mm_cvtps_epi32(b); - - // extract the 4 pixels RGB values. - // because we made sure values are between 0 and 255, we can just take the lower byte - // of each INT16 - pRGBImage[0] = piR[0]; - pRGBImage[1] = piG[0]; - pRGBImage[2] = piB[0]; - - pRGBImage[3] = piR[1]; - pRGBImage[4] = piG[1]; - pRGBImage[5] = piB[1]; - - pRGBImage[6] = piR[2]; - pRGBImage[7] = piG[2]; - pRGBImage[8] = piB[2]; - - pRGBImage[9] = piR[3]; - pRGBImage[10] = piG[3]; - pRGBImage[11] = piB[3]; - - // advance the streams - pYUVImage += 8; - pRGBImage += 12; - } - - *pnActualRead = pYUVImage - pYUVOrig; - *pnRGBSize = pRGBImage - pRGBOrig; -} - -#else // not Win32 - -void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize) -{ - const XnUInt8* pOrigYUV = pYUVImage; - const XnUInt8* pCurrYUV = pYUVImage; - const XnUInt8* pOrigRGB = pRGBImage; - XnUInt8* pCurrRGB = pRGBImage; - const XnUInt8* pLastYUV = pYUVImage + nYUVSize - YUV422_BPP; - const XnUInt8* pLastRGB = pRGBImage + *pnRGBSize - YUV_RGB_BPP; - - while (pCurrYUV <= pLastYUV && pCurrRGB <= pLastRGB) - { - YUV444ToRGB888(pCurrYUV[YUV422_Y1], pCurrYUV[YUV422_U], pCurrYUV[YUV422_V], - pCurrRGB[YUV_RED], pCurrRGB[YUV_GREEN], pCurrRGB[YUV_BLUE]); - pCurrRGB += YUV_RGB_BPP; - YUV444ToRGB888(pCurrYUV[YUV422_Y2], pCurrYUV[YUV422_U], pCurrYUV[YUV422_V], - pCurrRGB[YUV_RED], pCurrRGB[YUV_GREEN], pCurrRGB[YUV_BLUE]); - pCurrRGB += YUV_RGB_BPP; - pCurrYUV += YUV422_BPP; - } - - *pnActualRead = pCurrYUV - pOrigYUV; - *pnRGBSize = pCurrRGB - pOrigRGB; -} - -#endif - -void YUV420ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32 nRGBSize) -{ - const XnUInt8* pLastYUV = pYUVImage + nYUVSize - YUV420_BPP; - XnUInt8* pLastRGB = pRGBImage + nRGBSize - 12; - - while (pYUVImage < pLastYUV && pRGBImage < pYUVImage) - { - YUV444ToRGB888(pYUVImage[YUV420_Y1], pYUVImage[YUV420_U], pYUVImage[YUV420_V], - pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); - pRGBImage += YUV_RGB_BPP; - - YUV444ToRGB888(pYUVImage[YUV420_Y2], pYUVImage[YUV420_U], pYUVImage[YUV420_V], - pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); - pRGBImage += YUV_RGB_BPP; - - YUV444ToRGB888(pYUVImage[YUV420_Y3], pYUVImage[YUV420_U], pYUVImage[YUV420_V], - pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); - pRGBImage += YUV_RGB_BPP; - - YUV444ToRGB888(pYUVImage[YUV420_Y4], pYUVImage[YUV420_U], pYUVImage[YUV420_V], - pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); - pRGBImage += YUV_RGB_BPP; - - pYUVImage += YUV420_BPP; - } -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "YUV.h" +#include + +#if (XN_PLATFORM == XN_PLATFORM_WIN32) + #ifdef __INTEL_COMPILER + #include + #else + #include + #endif +#endif + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +void YUV444ToRGB888(XnUInt8 cY, XnUInt8 cU, XnUInt8 cV, + XnUInt8& cR, XnUInt8& cG, XnUInt8& cB) +{ + XnInt32 nC = cY - 16; + XnInt16 nD = cU - 128; + XnInt16 nE = cV - 128; + + nC = nC * 298 + 128; + + cR = XN_MIN(XN_MAX((nC + 409 * nE) >> 8, 0), 255); + cG = XN_MIN(XN_MAX((nC - 100 * nD - 208 * nE) >> 8, 0), 255); + cB = XN_MIN(XN_MAX((nC + 516 * nD ) >> 8, 0), 255); +} + +#if (XN_PLATFORM == XN_PLATFORM_WIN32) + +void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize) +{ + const XnUInt8* pYUVLast = pYUVImage + nYUVSize - 8; + const XnUInt8* pYUVOrig = pYUVImage; + const XnUInt8* pRGBOrig = pRGBImage; + const XnUInt8* pRGBLast = pRGBImage + *pnRGBSize - 12; + + const __m128 minus16 = _mm_set_ps1(-16); + const __m128 minus128 = _mm_set_ps1(-128); + const __m128 plus113983 = _mm_set_ps1(1.13983F); + const __m128 minus039466 = _mm_set_ps1(-0.39466F); + const __m128 minus058060 = _mm_set_ps1(-0.58060F); + const __m128 plus203211 = _mm_set_ps1(2.03211F); + const __m128 zero = _mm_set_ps1(0); + const __m128 plus255 = _mm_set_ps1(255); + + // define YUV floats + __m128 y; + __m128 u; + __m128 v; + + __m128 temp; + + // define RGB floats + __m128 r; + __m128 g; + __m128 b; + + // define RGB integers + __m128i iR; + __m128i iG; + __m128i iB; + + XnUInt32* piR = (XnUInt32*)&iR; + XnUInt32* piG = (XnUInt32*)&iG; + XnUInt32* piB = (XnUInt32*)&iB; + + while (pYUVImage <= pYUVLast && pRGBImage <= pRGBLast) + { + // process 4 pixels at once (values should be ordered backwards) + y = _mm_set_ps(pYUVImage[YUV422_Y2 + YUV422_BPP], pYUVImage[YUV422_Y1 + YUV422_BPP], pYUVImage[YUV422_Y2], pYUVImage[YUV422_Y1]); + u = _mm_set_ps(pYUVImage[YUV422_U + YUV422_BPP], pYUVImage[YUV422_U + YUV422_BPP], pYUVImage[YUV422_U], pYUVImage[YUV422_U]); + v = _mm_set_ps(pYUVImage[YUV422_V + YUV422_BPP], pYUVImage[YUV422_V + YUV422_BPP], pYUVImage[YUV422_V], pYUVImage[YUV422_V]); + + u = _mm_add_ps(u, minus128); // u -= 128 + v = _mm_add_ps(v, minus128); // v -= 128 + + /* + + http://en.wikipedia.org/wiki/YUV + + From YUV to RGB: + R = Y + 1.13983 V + G = Y - 0.39466 U - 0.58060 V + B = Y + 2.03211 U + + */ + + temp = _mm_mul_ps(plus113983, v); + r = _mm_add_ps(y, temp); + + temp = _mm_mul_ps(minus039466, u); + g = _mm_add_ps(y, temp); + temp = _mm_mul_ps(minus058060, v); + g = _mm_add_ps(g, temp); + + temp = _mm_mul_ps(plus203211, u); + b = _mm_add_ps(y, temp); + + // make sure no value is smaller than 0 + r = _mm_max_ps(r, zero); + g = _mm_max_ps(g, zero); + b = _mm_max_ps(b, zero); + + // make sure no value is bigger than 255 + r = _mm_min_ps(r, plus255); + g = _mm_min_ps(g, plus255); + b = _mm_min_ps(b, plus255); + + // convert floats to int16 (there is no conversion to uint8, just to int8). + iR = _mm_cvtps_epi32(r); + iG = _mm_cvtps_epi32(g); + iB = _mm_cvtps_epi32(b); + + // extract the 4 pixels RGB values. + // because we made sure values are between 0 and 255, we can just take the lower byte + // of each INT16 + pRGBImage[0] = piR[0]; + pRGBImage[1] = piG[0]; + pRGBImage[2] = piB[0]; + + pRGBImage[3] = piR[1]; + pRGBImage[4] = piG[1]; + pRGBImage[5] = piB[1]; + + pRGBImage[6] = piR[2]; + pRGBImage[7] = piG[2]; + pRGBImage[8] = piB[2]; + + pRGBImage[9] = piR[3]; + pRGBImage[10] = piG[3]; + pRGBImage[11] = piB[3]; + + // advance the streams + pYUVImage += 8; + pRGBImage += 12; + } + + *pnActualRead = pYUVImage - pYUVOrig; + *pnRGBSize = pRGBImage - pRGBOrig; +} + +#else // not Win32 + +void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize) +{ + const XnUInt8* pOrigYUV = pYUVImage; + const XnUInt8* pCurrYUV = pYUVImage; + const XnUInt8* pOrigRGB = pRGBImage; + XnUInt8* pCurrRGB = pRGBImage; + const XnUInt8* pLastYUV = pYUVImage + nYUVSize - YUV422_BPP; + const XnUInt8* pLastRGB = pRGBImage + *pnRGBSize - YUV_RGB_BPP; + + while (pCurrYUV <= pLastYUV && pCurrRGB <= pLastRGB) + { + YUV444ToRGB888(pCurrYUV[YUV422_Y1], pCurrYUV[YUV422_U], pCurrYUV[YUV422_V], + pCurrRGB[YUV_RED], pCurrRGB[YUV_GREEN], pCurrRGB[YUV_BLUE]); + pCurrRGB += YUV_RGB_BPP; + YUV444ToRGB888(pCurrYUV[YUV422_Y2], pCurrYUV[YUV422_U], pCurrYUV[YUV422_V], + pCurrRGB[YUV_RED], pCurrRGB[YUV_GREEN], pCurrRGB[YUV_BLUE]); + pCurrRGB += YUV_RGB_BPP; + pCurrYUV += YUV422_BPP; + } + + *pnActualRead = pCurrYUV - pOrigYUV; + *pnRGBSize = pCurrRGB - pOrigRGB; +} + +#endif + +void YUV420ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32 nRGBSize) +{ + const XnUInt8* pLastYUV = pYUVImage + nYUVSize - YUV420_BPP; + XnUInt8* pLastRGB = pRGBImage + nRGBSize - 12; + + while (pYUVImage < pLastYUV && pRGBImage < pYUVImage) + { + YUV444ToRGB888(pYUVImage[YUV420_Y1], pYUVImage[YUV420_U], pYUVImage[YUV420_V], + pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); + pRGBImage += YUV_RGB_BPP; + + YUV444ToRGB888(pYUVImage[YUV420_Y2], pYUVImage[YUV420_U], pYUVImage[YUV420_V], + pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); + pRGBImage += YUV_RGB_BPP; + + YUV444ToRGB888(pYUVImage[YUV420_Y3], pYUVImage[YUV420_U], pYUVImage[YUV420_V], + pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); + pRGBImage += YUV_RGB_BPP; + + YUV444ToRGB888(pYUVImage[YUV420_Y4], pYUVImage[YUV420_U], pYUVImage[YUV420_V], + pRGBImage[YUV_RED], pRGBImage[YUV_GREEN], pRGBImage[YUV_BLUE]); + pRGBImage += YUV_RGB_BPP; + + pYUVImage += YUV420_BPP; + } +} diff --git a/Source/XnDeviceSensorV2/YUV.h b/Source/XnDeviceSensorV2/YUV.h index 2634d72..516e22f 100644 --- a/Source/XnDeviceSensorV2/YUV.h +++ b/Source/XnDeviceSensorV2/YUV.h @@ -1,69 +1,69 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_YUV_H_ -#define _XN_YUV_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnDeviceSensor.h" - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define YUV422_U 0 -#define YUV422_Y1 1 -#define YUV422_V 2 -#define YUV422_Y2 3 -#define YUV422_BPP 4 - -#define YUV420_U 0 -#define YUV420_Y1 1 -#define YUV420_Y2 2 -#define YUV420_V 3 -#define YUV420_Y3 4 -#define YUV420_Y4 5 -#define YUV420_BPP 6 - -#define YUV_RED 0 -#define YUV_GREEN 1 -#define YUV_BLUE 2 -#define YUV_RGB_BPP 3 - -/* The size of an input element in the stream. */ -#define XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE 8 -/* The size of an output element in the stream. */ -#define XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE 12 - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize); -void YUV420ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32 nRGBSize); - -#endif //_XN_BAYER_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_YUV_H_ +#define _XN_YUV_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnDeviceSensor.h" + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define YUV422_U 0 +#define YUV422_Y1 1 +#define YUV422_V 2 +#define YUV422_Y2 3 +#define YUV422_BPP 4 + +#define YUV420_U 0 +#define YUV420_Y1 1 +#define YUV420_Y2 2 +#define YUV420_V 3 +#define YUV420_Y3 4 +#define YUV420_Y4 5 +#define YUV420_BPP 6 + +#define YUV_RED 0 +#define YUV_GREEN 1 +#define YUV_BLUE 2 +#define YUV_RGB_BPP 3 + +/* The size of an input element in the stream. */ +#define XN_YUV_TO_RGB_INPUT_ELEMENT_SIZE 8 +/* The size of an output element in the stream. */ +#define XN_YUV_TO_RGB_OUTPUT_ELEMENT_SIZE 12 + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +void YUV422ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32* pnActualRead, XnUInt32* pnRGBSize); +void YUV420ToRGB888(const XnUInt8* pYUVImage, XnUInt8* pRGBImage, XnUInt32 nYUVSize, XnUInt32 nRGBSize); + +#endif //_XN_BAYER_H_ diff --git a/Source/XnFormats/CMakeLists.txt b/Source/XnFormats/CMakeLists.txt new file mode 100644 index 0000000..2ffd254 --- /dev/null +++ b/Source/XnFormats/CMakeLists.txt @@ -0,0 +1,45 @@ +# Add search paths +# ---------------- +include_directories(${OPENNI_INCLUDE_DIR} + ${XNCORE_INCLUDE_DIR} + ${LIBJPEG_INCLUDE_DIR} + ../ +) + +# Get sources +# ------------ +file(GLOB ${XNFORMAT_LIB_NAME}_sources ./*.cpp) + +# Add the library +# --------------- +add_library( + ${XNFORMAT_LIB_NAME} + SHARED + ${${XNFORMAT_LIB_NAME}_sources} +) + +target_link_libraries( + ${XNFORMAT_LIB_NAME} + ${LIBJPEG_LIB_NAME} + ${XNCORE_LIB_NAME} +) + +# The install_name is Mac OSX specific and is used to set the RPATH on a executable +# On Mac OSX the library can hold information for the rpath of the executable which +# uses the library. +# ---------------------------------------------------------------------------------- +if(SENSOR_PLATFORM_MAC) + set_target_properties(${XNFORMAT_LIB_NAME} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR ${INSTALL_NAME_VALUE} + ) +endif() + +# Set install dir +# --------------- +install( + TARGETS ${XNFORMAT_LIB_NAME} + LIBRARY DESTINATION ${LIB_INSTALL_PATH} + RUNTIME DESTINATION ${BIN_INSTALL_PATH} +) + diff --git a/Source/XnFormats/Xn16zCodec.h b/Source/XnFormats/Xn16zCodec.h index 27bc664..02844e0 100644 --- a/Source/XnFormats/Xn16zCodec.h +++ b/Source/XnFormats/Xn16zCodec.h @@ -1,59 +1,59 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_16Z_CODEC_H__ -#define __XN_16Z_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecBase.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API Xn16zCodec : public XnCodecBase -{ -public: - virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_16Z; } - - virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO; } - virtual XnUInt32 GetOverheadSize() const { return 0; } - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - return XnStreamCompressDepth16Z((XnUInt16*)pData, nDataSize, pCompressedData, pnCompressedDataSize); - } - - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - return XnStreamUncompressDepth16Z(pCompressedData, nCompressedDataSize, (XnUInt16*)pData, pnDataSize); - } -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_16Z_CODEC_H__ +#define __XN_16Z_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecBase.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API Xn16zCodec : public XnCodecBase +{ +public: + virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_16Z; } + + virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO; } + virtual XnUInt32 GetOverheadSize() const { return 0; } + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + return XnStreamCompressDepth16Z((XnUInt16*)pData, nDataSize, pCompressedData, pnCompressedDataSize); + } + + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + return XnStreamUncompressDepth16Z(pCompressedData, nCompressedDataSize, (XnUInt16*)pData, pnDataSize); + } +}; + #endif //__XN_16Z_CODEC_H__ \ No newline at end of file diff --git a/Source/XnFormats/Xn16zEmbTablesCodec.h b/Source/XnFormats/Xn16zEmbTablesCodec.h index 44a35dc..45213dc 100644 --- a/Source/XnFormats/Xn16zEmbTablesCodec.h +++ b/Source/XnFormats/Xn16zEmbTablesCodec.h @@ -1,64 +1,64 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_16Z_EMB_TABLES_CODEC_H__ -#define __XN_16Z_EMB_TABLES_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecBase.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API Xn16zEmbTablesCodec : public XnCodecBase -{ -public: - Xn16zEmbTablesCodec(XnUInt16 nMaxValue) : m_nMaxValue(nMaxValue) {} - - virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_16Z_EMB_TABLE; } - - virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO; } - virtual XnUInt32 GetOverheadSize() const { return m_nMaxValue * sizeof(XnUInt16); } - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - return XnStreamCompressDepth16ZWithEmbTable((XnUInt16*)pData, nDataSize, pCompressedData, pnCompressedDataSize, m_nMaxValue); - } - - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - return XnStreamUncompressDepth16ZWithEmbTable(pCompressedData, nCompressedDataSize, (XnUInt16*)pData, pnDataSize); - } - -private: - XnUInt16 m_nMaxValue; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_16Z_EMB_TABLES_CODEC_H__ +#define __XN_16Z_EMB_TABLES_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecBase.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API Xn16zEmbTablesCodec : public XnCodecBase +{ +public: + Xn16zEmbTablesCodec(XnUInt16 nMaxValue) : m_nMaxValue(nMaxValue) {} + + virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_16Z_EMB_TABLE; } + + virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO; } + virtual XnUInt32 GetOverheadSize() const { return m_nMaxValue * sizeof(XnUInt16); } + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + return XnStreamCompressDepth16ZWithEmbTable((XnUInt16*)pData, nDataSize, pCompressedData, pnCompressedDataSize, m_nMaxValue); + } + + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + return XnStreamUncompressDepth16ZWithEmbTable(pCompressedData, nCompressedDataSize, (XnUInt16*)pData, pnDataSize); + } + +private: + XnUInt16 m_nMaxValue; +}; + #endif //__XN_16Z_EMB_TABLES_CODEC_H__ \ No newline at end of file diff --git a/Source/XnFormats/Xn8zCodec.h b/Source/XnFormats/Xn8zCodec.h index 1b9f24c..36009fe 100644 --- a/Source/XnFormats/Xn8zCodec.h +++ b/Source/XnFormats/Xn8zCodec.h @@ -1,58 +1,58 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_8Z_CODEC_H__ -#define __XN_8Z_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecBase.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API Xn8zCodec : public XnCodecBase -{ -public: - virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_COLOR_8Z; } - virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO; } - virtual XnUInt32 GetOverheadSize() const { return 0; } - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - return XnStreamCompressImage8Z(pData, nDataSize, pCompressedData, pnCompressedDataSize); - } - - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - return XnStreamUncompressImage8Z(pCompressedData, nCompressedDataSize, pData, pnDataSize); - } -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_8Z_CODEC_H__ +#define __XN_8Z_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecBase.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API Xn8zCodec : public XnCodecBase +{ +public: + virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_COLOR_8Z; } + virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO; } + virtual XnUInt32 GetOverheadSize() const { return 0; } + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + return XnStreamCompressImage8Z(pData, nDataSize, pCompressedData, pnCompressedDataSize); + } + + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + return XnStreamUncompressImage8Z(pCompressedData, nCompressedDataSize, pData, pnDataSize); + } +}; + #endif //__XN_8Z_CODEC_H__ \ No newline at end of file diff --git a/Source/XnFormats/XnCodec.h b/Source/XnFormats/XnCodec.h index 8718997..f1d0d74 100644 --- a/Source/XnFormats/XnCodec.h +++ b/Source/XnFormats/XnCodec.h @@ -1,60 +1,60 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_CODEC_H__ -#define __XN_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include "XnFormats.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API XnCodec -{ -public: - static XnCompressionFormats GetCompressionFormatFromCodecID(XnCodecID codecID); - static XnCodecID GetCodecIDFromCompressionFormat(XnCompressionFormats format); - - XnCodec() {} - virtual ~XnCodec() {} - - virtual XnStatus Init() { return XN_STATUS_OK; } - - virtual XnCompressionFormats GetCompressionFormat() const = 0; - - virtual XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) = 0; - - virtual XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) = 0; -}; - -#endif //__XN_CODEC_H__ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_CODEC_H__ +#define __XN_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include "XnFormats.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API XnCodec +{ +public: + static XnCompressionFormats GetCompressionFormatFromCodecID(XnCodecID codecID); + static XnCodecID GetCodecIDFromCompressionFormat(XnCompressionFormats format); + + XnCodec() {} + virtual ~XnCodec() {} + + virtual XnStatus Init() { return XN_STATUS_OK; } + + virtual XnCompressionFormats GetCompressionFormat() const = 0; + + virtual XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) = 0; + + virtual XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) = 0; +}; + +#endif //__XN_CODEC_H__ diff --git a/Source/XnFormats/XnCodecBase.h b/Source/XnFormats/XnCodecBase.h index bef220f..448d856 100644 --- a/Source/XnFormats/XnCodecBase.h +++ b/Source/XnFormats/XnCodecBase.h @@ -1,93 +1,93 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_CODEC_BASE_H__ -#define __XN_CODEC_BASE_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodec.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API XnCodecBase : public XnCodec -{ -public: - static XnCompressionFormats GetCompressionFormatFromCodecID(XnCodecID codecID); - static XnCodecID GetCodecIDFromCompressionFormat(XnCompressionFormats format); - - XnCodecBase() {} - virtual ~XnCodecBase() {} - - virtual XnStatus Init() { return XN_STATUS_OK; } - - virtual XnCompressionFormats GetCompressionFormat() const = 0; - - XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pData); - XN_VALIDATE_INPUT_PTR(pCompressedData); - XN_VALIDATE_OUTPUT_PTR(pnCompressedDataSize); - - if ((nDataSize * GetWorseCompressionRatio() + GetOverheadSize()) > *pnCompressedDataSize) - { - return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; - } - - nRetVal = CompressImpl(pData, nDataSize, pCompressedData, pnCompressedDataSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); - } - - XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - XnStatus nRetVal = XN_STATUS_OK; - - XN_VALIDATE_INPUT_PTR(pCompressedData); - XN_VALIDATE_INPUT_PTR(pData); - XN_VALIDATE_OUTPUT_PTR(pnDataSize); - - nRetVal = DecompressImpl(pCompressedData, nCompressedDataSize, pData, pnDataSize); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); - } - - virtual XnUInt32 GetOverheadSize() const = 0; - virtual XnFloat GetWorseCompressionRatio() const = 0; - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) = 0; - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) = 0; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_CODEC_BASE_H__ +#define __XN_CODEC_BASE_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodec.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API XnCodecBase : public XnCodec +{ +public: + static XnCompressionFormats GetCompressionFormatFromCodecID(XnCodecID codecID); + static XnCodecID GetCodecIDFromCompressionFormat(XnCompressionFormats format); + + XnCodecBase() {} + virtual ~XnCodecBase() {} + + virtual XnStatus Init() { return XN_STATUS_OK; } + + virtual XnCompressionFormats GetCompressionFormat() const = 0; + + XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pData); + XN_VALIDATE_INPUT_PTR(pCompressedData); + XN_VALIDATE_OUTPUT_PTR(pnCompressedDataSize); + + if ((nDataSize * GetWorseCompressionRatio() + GetOverheadSize()) > *pnCompressedDataSize) + { + return XN_STATUS_OUTPUT_BUFFER_OVERFLOW; + } + + nRetVal = CompressImpl(pData, nDataSize, pCompressedData, pnCompressedDataSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); + } + + XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + XnStatus nRetVal = XN_STATUS_OK; + + XN_VALIDATE_INPUT_PTR(pCompressedData); + XN_VALIDATE_INPUT_PTR(pData); + XN_VALIDATE_OUTPUT_PTR(pnDataSize); + + nRetVal = DecompressImpl(pCompressedData, nCompressedDataSize, pData, pnDataSize); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); + } + + virtual XnUInt32 GetOverheadSize() const = 0; + virtual XnFloat GetWorseCompressionRatio() const = 0; + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) = 0; + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) = 0; +}; + #endif // __XN_CODEC_BASE_H__ \ No newline at end of file diff --git a/Source/XnFormats/XnCodecs.cpp b/Source/XnFormats/XnCodecs.cpp index 12b2ebd..a9aa40c 100644 --- a/Source/XnFormats/XnCodecs.cpp +++ b/Source/XnFormats/XnCodecs.cpp @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnUncompressedCodec.h" -#include "Xn16zCodec.h" -#include "Xn16zEmbTablesCodec.h" -#include "Xn8zCodec.h" -#include "XnJpegCodec.h" -#include "XnNiCodec.h" - -XnCompressionFormats XnCodec::GetCompressionFormatFromCodecID(XnCodecID codecID) -{ - switch (codecID) - { - case XN_CODEC_UNCOMPRESSED: - return XN_COMPRESSION_NONE; - case XN_CODEC_16Z: - return XN_COMPRESSION_16Z; - case XN_CODEC_16Z_EMB_TABLES: - return XN_COMPRESSION_16Z_EMB_TABLE; - case XN_CODEC_8Z: - return XN_COMPRESSION_COLOR_8Z; - case XN_CODEC_JPEG: - return XN_COMPRESSION_JPEG; - default: - return (XnCompressionFormats)-1; - } -} - -XnCodecID XnCodec::GetCodecIDFromCompressionFormat(XnCompressionFormats format) -{ - switch (format) - { - case XN_COMPRESSION_16Z: - return XN_CODEC_16Z; - case XN_COMPRESSION_16Z_EMB_TABLE: - return XN_CODEC_16Z_EMB_TABLES; - case XN_COMPRESSION_JPEG: - return XN_CODEC_JPEG; - case XN_COMPRESSION_NONE: - return XN_CODEC_UNCOMPRESSED; - case XN_COMPRESSION_COLOR_8Z: - return XN_CODEC_8Z; - default: - return XN_CODEC_NULL; - } -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnUncompressedCodec.h" +#include "Xn16zCodec.h" +#include "Xn16zEmbTablesCodec.h" +#include "Xn8zCodec.h" +#include "XnJpegCodec.h" +#include "XnNiCodec.h" + +XnCompressionFormats XnCodec::GetCompressionFormatFromCodecID(XnCodecID codecID) +{ + switch (codecID) + { + case XN_CODEC_UNCOMPRESSED: + return XN_COMPRESSION_NONE; + case XN_CODEC_16Z: + return XN_COMPRESSION_16Z; + case XN_CODEC_16Z_EMB_TABLES: + return XN_COMPRESSION_16Z_EMB_TABLE; + case XN_CODEC_8Z: + return XN_COMPRESSION_COLOR_8Z; + case XN_CODEC_JPEG: + return XN_COMPRESSION_JPEG; + default: + return (XnCompressionFormats)-1; + } +} + +XnCodecID XnCodec::GetCodecIDFromCompressionFormat(XnCompressionFormats format) +{ + switch (format) + { + case XN_COMPRESSION_16Z: + return XN_CODEC_16Z; + case XN_COMPRESSION_16Z_EMB_TABLE: + return XN_CODEC_16Z_EMB_TABLES; + case XN_COMPRESSION_JPEG: + return XN_CODEC_JPEG; + case XN_COMPRESSION_NONE: + return XN_CODEC_UNCOMPRESSED; + case XN_COMPRESSION_COLOR_8Z: + return XN_CODEC_8Z; + default: + return XN_CODEC_NULL; + } +} diff --git a/Source/XnFormats/XnFormats.cpp b/Source/XnFormats/XnFormats.cpp index 37cb216..56522df 100644 --- a/Source/XnFormats/XnFormats.cpp +++ b/Source/XnFormats/XnFormats.cpp @@ -1,119 +1,119 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFormats.h" -#include -#include - -// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! -XN_API_EXPORT_INIT() - -//--------------------------------------------------------------------------- -// Global Variables -//--------------------------------------------------------------------------- -static XnBool g_XnFormatsWasInit = FALSE; - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_FORMATS_API XnStatus XnFormatsInit() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Was the Formats subsystem already initialized? - if (g_XnFormatsWasInit == FALSE) - { - // Init the core subsystem - nRetVal = XnInit(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) - return nRetVal; - - g_XnFormatsWasInit = TRUE; - } - else - { - // Trying to init twice... - return (XN_STATUS_ALREADY_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnFormatsInitFromINIFile(const XnChar* cpINIFileName) -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(cpINIFileName); - - // Was the Formats subsystem already initialized? - if (g_XnFormatsWasInit == FALSE) - { - // Init the core subsystem - nRetVal = XnInitFromINIFile(cpINIFileName); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) - return nRetVal; - - g_XnFormatsWasInit = TRUE; - } - else - { - // Trying to init twice... - return (XN_STATUS_ALREADY_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnFormatsShutdown() -{ - XnStatus nRetVal = XN_STATUS_OK; - - // Was the Formats subsystem initialized? - if (g_XnFormatsWasInit == TRUE) - { - // Shutdown the core subsystem - nRetVal = XnShutdown(); - if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_NOT_INIT) - return nRetVal; - - g_XnFormatsWasInit = FALSE; - } - else - { - // Trying to shutdown without doing init... - return (XN_STATUS_FORMATS_NOT_INIT); - } - - // All is good... - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFormats.h" +#include +#include + +// The following line is needed to be once in *ALL* of the high level shared library modules. DO NOT REMOVE!!! +XN_API_EXPORT_INIT() + +//--------------------------------------------------------------------------- +// Global Variables +//--------------------------------------------------------------------------- +static XnBool g_XnFormatsWasInit = FALSE; + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_FORMATS_API XnStatus XnFormatsInit() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Was the Formats subsystem already initialized? + if (g_XnFormatsWasInit == FALSE) + { + // Init the core subsystem + nRetVal = XnInit(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) + return nRetVal; + + g_XnFormatsWasInit = TRUE; + } + else + { + // Trying to init twice... + return (XN_STATUS_ALREADY_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnFormatsInitFromINIFile(const XnChar* cpINIFileName) +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(cpINIFileName); + + // Was the Formats subsystem already initialized? + if (g_XnFormatsWasInit == FALSE) + { + // Init the core subsystem + nRetVal = XnInitFromINIFile(cpINIFileName); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_ALREADY_INIT) + return nRetVal; + + g_XnFormatsWasInit = TRUE; + } + else + { + // Trying to init twice... + return (XN_STATUS_ALREADY_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnFormatsShutdown() +{ + XnStatus nRetVal = XN_STATUS_OK; + + // Was the Formats subsystem initialized? + if (g_XnFormatsWasInit == TRUE) + { + // Shutdown the core subsystem + nRetVal = XnShutdown(); + if (nRetVal != XN_STATUS_OK && nRetVal != XN_STATUS_NOT_INIT) + return nRetVal; + + g_XnFormatsWasInit = FALSE; + } + else + { + // Trying to shutdown without doing init... + return (XN_STATUS_FORMATS_NOT_INIT); + } + + // All is good... + return (XN_STATUS_OK); +} diff --git a/Source/XnFormats/XnFormats.h b/Source/XnFormats/XnFormats.h index 80779cc..689d95c 100644 --- a/Source/XnFormats/XnFormats.h +++ b/Source/XnFormats/XnFormats.h @@ -1,91 +1,91 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_FORMATS_H_ -#define _XN_FORMATS_H_ - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#ifdef __cplusplus - #ifdef XN_FORMATS_EXPORTS - #define XN_FORMATS_API extern "C" XN_API_EXPORT - #define XN_FORMATS_CPP_API XN_API_EXPORT - #else - #define XN_FORMATS_API extern "C" XN_API_IMPORT - #define XN_FORMATS_CPP_API XN_API_IMPORT - #endif -#else - #ifdef XN_FORMATS_EXPORTS - #define XN_FORMATS_API XN_API_EXPORT - #else - #define XN_FORMATS_API XN_API_IMPORT - #endif -#endif - -#define XN_MASK_FORMATS "XnFormats" - -//--------------------------------------------------------------------------- -// Exported Functions -//--------------------------------------------------------------------------- - -/** -* This function initializes the formats library. -*/ -XN_FORMATS_API XnStatus XnFormatsInit(); - -/** -* This function initializes the formats library from an INI file. -* -* @param cpINIFileName [in] The name of the INI file. -*/ -XN_FORMATS_API XnStatus XnFormatsInitFromINIFile(const XnChar* cpINIFileName); - -/** -* This function shuts down the formats library. -*/ -XN_FORMATS_API XnStatus XnFormatsShutdown(); - -/** -* This function receives a buffer of pixel data of a known format, and mirrors it. -* -* @param nOutputFormat [in] The format of the pixel data. -* @param pBuffer [in] A pointer to the buffer. -* @param nBufferSize [in] The size of the buffer, in bytes. -* @param nXRes [in] X-resolution (line size in pixels) of the buffer. -*/ -XN_FORMATS_API XnStatus XnFormatsMirrorPixelData(XnOutputFormats nOutputFormat, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes); - -#endif //_XN_FORMATS_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_FORMATS_H_ +#define _XN_FORMATS_H_ + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#ifdef __cplusplus + #ifdef XN_FORMATS_EXPORTS + #define XN_FORMATS_API extern "C" XN_API_EXPORT + #define XN_FORMATS_CPP_API XN_API_EXPORT + #else + #define XN_FORMATS_API extern "C" XN_API_IMPORT + #define XN_FORMATS_CPP_API XN_API_IMPORT + #endif +#else + #ifdef XN_FORMATS_EXPORTS + #define XN_FORMATS_API XN_API_EXPORT + #else + #define XN_FORMATS_API XN_API_IMPORT + #endif +#endif + +#define XN_MASK_FORMATS "XnFormats" + +//--------------------------------------------------------------------------- +// Exported Functions +//--------------------------------------------------------------------------- + +/** +* This function initializes the formats library. +*/ +XN_FORMATS_API XnStatus XnFormatsInit(); + +/** +* This function initializes the formats library from an INI file. +* +* @param cpINIFileName [in] The name of the INI file. +*/ +XN_FORMATS_API XnStatus XnFormatsInitFromINIFile(const XnChar* cpINIFileName); + +/** +* This function shuts down the formats library. +*/ +XN_FORMATS_API XnStatus XnFormatsShutdown(); + +/** +* This function receives a buffer of pixel data of a known format, and mirrors it. +* +* @param nOutputFormat [in] The format of the pixel data. +* @param pBuffer [in] A pointer to the buffer. +* @param nBufferSize [in] The size of the buffer, in bytes. +* @param nXRes [in] X-resolution (line size in pixels) of the buffer. +*/ +XN_FORMATS_API XnStatus XnFormatsMirrorPixelData(XnOutputFormats nOutputFormat, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes); + +#endif //_XN_FORMATS_H_ diff --git a/Source/XnFormats/XnFormatsMirror.cpp b/Source/XnFormats/XnFormatsMirror.cpp index 3bb3834..f3f0b5b 100644 --- a/Source/XnFormats/XnFormatsMirror.cpp +++ b/Source/XnFormats/XnFormatsMirror.cpp @@ -1,228 +1,228 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include -#include -#include "XnFormats.h" -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_MIRROR_MAX_LINE_SIZE 1920*3 - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XnStatus XnMirrorOneBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) -{ - // Local function variables - XnUInt8* pSrc = pBuffer; - XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; - XnUInt8* pSrcEnd = pSrc + nBufferSize; - XnUInt8* pDest = NULL; - XnUInt8* pDestVal = &pLineBuffer[0] + nLineSize - 1; - XnUInt8* pDestEnd = &pLineBuffer[0] - 1; - - if (nLineSize > XN_MIRROR_MAX_LINE_SIZE) - { - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - } - - while (pSrc < pSrcEnd) - { - xnOSMemCopy(pLineBuffer, pSrc, nLineSize); - - pDest = pDestVal; - while (pDest != pDestEnd) - { - *pSrc = *pDest; - - pSrc++; - pDest--; - } - } - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnMirrorTwoBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) -{ - // Local function variables - XnUInt16* pSrc = (XnUInt16*)pBuffer; - XnUInt16 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; - XnUInt16* pSrcEnd = pSrc + nBufferSize / sizeof(XnUInt16); - XnUInt16* pDest = NULL; - XnUInt16* pDestVal = &pLineBuffer[0] + nLineSize - 1; - XnUInt16* pDestEnd = &pLineBuffer[0] - 1; - XnUInt16 nMemCpyLineSize = nLineSize * sizeof(XnUInt16); - XnUInt16 nValue; - - if (nLineSize > XN_MIRROR_MAX_LINE_SIZE) - { - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - } - - while (pSrc < pSrcEnd) - { - xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); - - pDest = pDestVal; - while (pDest != pDestEnd) - { - nValue = pDest[0]; - pSrc[0] = nValue; - - pDest--; - pSrc++; - } - } - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnMirrorThreeBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) -{ - // Local function variables - XnUInt8* pSrc = pBuffer; - XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; - XnUInt8* pSrcEnd = pSrc + nBufferSize; - XnUInt8* pDest = NULL; - XnUInt8* pDestVal = &pLineBuffer[0] + nLineSize * 3 - 1; - XnUInt8* pDestEnd = &pLineBuffer[0] - 1; - XnUInt16 nMemCpyLineSize = nLineSize * 3; - - if (nMemCpyLineSize > XN_MIRROR_MAX_LINE_SIZE) - { - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - } - - while (pSrc < pSrcEnd) - { - xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); - - pDest = pDestVal; - while (pDest != pDestEnd) - { - *pSrc = *(pDest-2); - *(pSrc+1) = *(pDest-1); - *(pSrc+2) = *pDest; - - pSrc+=3; - pDest-=3; - } - } - - // All is good... - return (XN_STATUS_OK); -} - -XnStatus XnMirrorYUV422Pixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) -{ - // Local function variables - XnUInt8* pSrc = pBuffer; - XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; - XnUInt8* pSrcEnd = (XnUInt8*)pSrc + nBufferSize; - XnUInt8* pDest = NULL; - XnUInt8* pDestVal = &pLineBuffer[(nLineSize/2-1)*sizeof(XnUInt32)]; // last element - XnUInt8* pDestEnd = &pLineBuffer[0]; // first element - XnUInt32 nMemCpyLineSize = nLineSize/2*sizeof(XnUInt32); - - if (nMemCpyLineSize > XN_MIRROR_MAX_LINE_SIZE) - { - return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); - } - - while (pSrc < pSrcEnd) - { - xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); - pDest = pDestVal; - - while (pDest >= pDestEnd) - { - pSrc[0] = pDest[0]; // u - pSrc[1] = pDest[3]; // y1 <-> y2 - pSrc[2] = pDest[2]; // v - pSrc[3] = pDest[1]; // y2 <-> y1 - - pSrc += 4; - pDest -= 4; - } - } - - // All is good... - return (XN_STATUS_OK); -} - -typedef XnStatus (*XnMirrorFunc)(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes); - -typedef struct -{ - XnMirrorFunc MirrorFunctions[XN_OUTPUT_FORMATS_COUNT]; -} XnMirrorFunctions; - -XnMirrorFunctions XnMirrorGetFunctionsMap() -{ - XnMirrorFunctions result; - xnOSMemSet(&result, 0, sizeof(XnMirrorFunctions)); - result.MirrorFunctions[XN_OUTPUT_FORMAT_SHIFT_VALUES] = XnMirrorTwoBytePixels; - result.MirrorFunctions[XN_OUTPUT_FORMAT_DEPTH_VALUES] = XnMirrorTwoBytePixels; - result.MirrorFunctions[XN_OUTPUT_FORMAT_GRAYSCALE8] = XnMirrorOneBytePixels; - result.MirrorFunctions[XN_OUTPUT_FORMAT_GRAYSCALE16] = XnMirrorTwoBytePixels; - result.MirrorFunctions[XN_OUTPUT_FORMAT_YUV422] = XnMirrorYUV422Pixels; - result.MirrorFunctions[XN_OUTPUT_FORMAT_RGB24] = XnMirrorThreeBytePixels; - return result; -} - -XN_FORMATS_API XnStatus XnFormatsMirrorPixelData(XnOutputFormats nOutputFormat, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes) -{ - static XnMirrorFunctions FunctionsMap = XnMirrorGetFunctionsMap(); - - XnStatus nRetVal = XN_STATUS_OK; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pBuffer); - - XnMirrorFunc pFunc = FunctionsMap.MirrorFunctions[nOutputFormat]; - if (pFunc == NULL) - { - xnLogError(XN_MASK_FORMATS, "Mirror was not implemented for output format %d", nOutputFormat); - return XN_STATUS_ERROR; - } - - // perform mirror - nRetVal = pFunc(pBuffer, nBufferSize, nXRes); - XN_IS_STATUS_OK(nRetVal); - - return (XN_STATUS_OK); +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include +#include +#include "XnFormats.h" +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_MIRROR_MAX_LINE_SIZE 1920*3 + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XnStatus XnMirrorOneBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) +{ + // Local function variables + XnUInt8* pSrc = pBuffer; + XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; + XnUInt8* pSrcEnd = pSrc + nBufferSize; + XnUInt8* pDest = NULL; + XnUInt8* pDestVal = &pLineBuffer[0] + nLineSize - 1; + XnUInt8* pDestEnd = &pLineBuffer[0] - 1; + + if (nLineSize > XN_MIRROR_MAX_LINE_SIZE) + { + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + } + + while (pSrc < pSrcEnd) + { + xnOSMemCopy(pLineBuffer, pSrc, nLineSize); + + pDest = pDestVal; + while (pDest != pDestEnd) + { + *pSrc = *pDest; + + pSrc++; + pDest--; + } + } + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnMirrorTwoBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) +{ + // Local function variables + XnUInt16* pSrc = (XnUInt16*)pBuffer; + XnUInt16 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; + XnUInt16* pSrcEnd = pSrc + nBufferSize / sizeof(XnUInt16); + XnUInt16* pDest = NULL; + XnUInt16* pDestVal = &pLineBuffer[0] + nLineSize - 1; + XnUInt16* pDestEnd = &pLineBuffer[0] - 1; + XnUInt16 nMemCpyLineSize = nLineSize * sizeof(XnUInt16); + XnUInt16 nValue; + + if (nLineSize > XN_MIRROR_MAX_LINE_SIZE) + { + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + } + + while (pSrc < pSrcEnd) + { + xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); + + pDest = pDestVal; + while (pDest != pDestEnd) + { + nValue = pDest[0]; + pSrc[0] = nValue; + + pDest--; + pSrc++; + } + } + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnMirrorThreeBytePixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) +{ + // Local function variables + XnUInt8* pSrc = pBuffer; + XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; + XnUInt8* pSrcEnd = pSrc + nBufferSize; + XnUInt8* pDest = NULL; + XnUInt8* pDestVal = &pLineBuffer[0] + nLineSize * 3 - 1; + XnUInt8* pDestEnd = &pLineBuffer[0] - 1; + XnUInt16 nMemCpyLineSize = nLineSize * 3; + + if (nMemCpyLineSize > XN_MIRROR_MAX_LINE_SIZE) + { + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + } + + while (pSrc < pSrcEnd) + { + xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); + + pDest = pDestVal; + while (pDest != pDestEnd) + { + *pSrc = *(pDest-2); + *(pSrc+1) = *(pDest-1); + *(pSrc+2) = *pDest; + + pSrc+=3; + pDest-=3; + } + } + + // All is good... + return (XN_STATUS_OK); +} + +XnStatus XnMirrorYUV422Pixels(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nLineSize) +{ + // Local function variables + XnUInt8* pSrc = pBuffer; + XnUInt8 pLineBuffer[XN_MIRROR_MAX_LINE_SIZE]; + XnUInt8* pSrcEnd = (XnUInt8*)pSrc + nBufferSize; + XnUInt8* pDest = NULL; + XnUInt8* pDestVal = &pLineBuffer[(nLineSize/2-1)*sizeof(XnUInt32)]; // last element + XnUInt8* pDestEnd = &pLineBuffer[0]; // first element + XnUInt32 nMemCpyLineSize = nLineSize/2*sizeof(XnUInt32); + + if (nMemCpyLineSize > XN_MIRROR_MAX_LINE_SIZE) + { + return (XN_STATUS_INTERNAL_BUFFER_TOO_SMALL); + } + + while (pSrc < pSrcEnd) + { + xnOSMemCopy(pLineBuffer, pSrc, nMemCpyLineSize); + pDest = pDestVal; + + while (pDest >= pDestEnd) + { + pSrc[0] = pDest[0]; // u + pSrc[1] = pDest[3]; // y1 <-> y2 + pSrc[2] = pDest[2]; // v + pSrc[3] = pDest[1]; // y2 <-> y1 + + pSrc += 4; + pDest -= 4; + } + } + + // All is good... + return (XN_STATUS_OK); +} + +typedef XnStatus (*XnMirrorFunc)(XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes); + +typedef struct +{ + XnMirrorFunc MirrorFunctions[XN_OUTPUT_FORMATS_COUNT]; +} XnMirrorFunctions; + +XnMirrorFunctions XnMirrorGetFunctionsMap() +{ + XnMirrorFunctions result; + xnOSMemSet(&result, 0, sizeof(XnMirrorFunctions)); + result.MirrorFunctions[XN_OUTPUT_FORMAT_SHIFT_VALUES] = XnMirrorTwoBytePixels; + result.MirrorFunctions[XN_OUTPUT_FORMAT_DEPTH_VALUES] = XnMirrorTwoBytePixels; + result.MirrorFunctions[XN_OUTPUT_FORMAT_GRAYSCALE8] = XnMirrorOneBytePixels; + result.MirrorFunctions[XN_OUTPUT_FORMAT_GRAYSCALE16] = XnMirrorTwoBytePixels; + result.MirrorFunctions[XN_OUTPUT_FORMAT_YUV422] = XnMirrorYUV422Pixels; + result.MirrorFunctions[XN_OUTPUT_FORMAT_RGB24] = XnMirrorThreeBytePixels; + return result; +} + +XN_FORMATS_API XnStatus XnFormatsMirrorPixelData(XnOutputFormats nOutputFormat, XnUChar* pBuffer, XnUInt32 nBufferSize, XnUInt32 nXRes) +{ + static XnMirrorFunctions FunctionsMap = XnMirrorGetFunctionsMap(); + + XnStatus nRetVal = XN_STATUS_OK; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pBuffer); + + XnMirrorFunc pFunc = FunctionsMap.MirrorFunctions[nOutputFormat]; + if (pFunc == NULL) + { + xnLogError(XN_MASK_FORMATS, "Mirror was not implemented for output format %d", nOutputFormat); + return XN_STATUS_ERROR; + } + + // perform mirror + nRetVal = pFunc(pBuffer, nBufferSize, nXRes); + XN_IS_STATUS_OK(nRetVal); + + return (XN_STATUS_OK); } \ No newline at end of file diff --git a/Source/XnFormats/XnFormatsStatus.cpp b/Source/XnFormats/XnFormatsStatus.cpp index cd5d309..aa696c5 100644 --- a/Source/XnFormats/XnFormatsStatus.cpp +++ b/Source/XnFormats/XnFormatsStatus.cpp @@ -1,34 +1,34 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -// registration is done by including XnStatusRegister *before* including the list of errors -#include -#define XN_MESSAGE_MAP_REGISTER -#include "XnFormatsStatus.h" +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +// registration is done by including XnStatusRegister *before* including the list of errors +#include +#define XN_MESSAGE_MAP_REGISTER +#include "XnFormatsStatus.h" diff --git a/Source/XnFormats/XnJpegCodec.h b/Source/XnFormats/XnJpegCodec.h index 40728e0..eedaf3c 100644 --- a/Source/XnFormats/XnJpegCodec.h +++ b/Source/XnFormats/XnJpegCodec.h @@ -1,100 +1,100 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_JPEG_CODEC_H__ -#define __XN_JPEG_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecBase.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API XnJpegCodec : public XnCodecBase -{ -public: - XnJpegCodec(XnBool bRGB, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nQuality = XN_STREAM_COMPRESSION_JPEG_DEFAULT_QUALITY) : - m_bRGB(bRGB), m_nXRes(nXRes), m_nYRes(nYRes), m_nQuality(nQuality) - {} - - ~XnJpegCodec() - { - XnStreamFreeCompressImageJ(&m_CompJPEGContext); - XnStreamFreeUncompressImageJ(&m_UncompJPEGContext); - } - - XnStatus Init() - { - XnStatus nRetVal = XN_STATUS_OK; - - nRetVal = XnStreamInitCompressImageJ(&m_CompJPEGContext); - XN_IS_STATUS_OK(nRetVal); - - nRetVal = XnStreamInitUncompressImageJ(&m_UncompJPEGContext); - if (nRetVal != XN_STATUS_OK) - { - XnStreamFreeCompressImageJ(&m_CompJPEGContext); - return (nRetVal); - } - - return (XN_STATUS_OK); - } - - virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_JPEG; } - virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO; } - virtual XnUInt32 GetOverheadSize() const { return 0; } - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - if (m_bRGB) - { - return XnStreamCompressImage24J(&m_CompJPEGContext, pData, pCompressedData, pnCompressedDataSize, m_nXRes, m_nYRes, m_nQuality); - } - else - { - return XnStreamCompressImage8J(&m_CompJPEGContext, pData, pCompressedData, pnCompressedDataSize, m_nXRes, m_nYRes, m_nQuality); - } - } - - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - return XnStreamUncompressImageJ(&m_UncompJPEGContext, pCompressedData, nCompressedDataSize, pData, pnDataSize); - } - -private: - const XnBool m_bRGB; - const XnUInt32 m_nXRes; - const XnUInt32 m_nYRes; - const XnUInt32 m_nQuality; - XnStreamCompJPEGContext m_CompJPEGContext; - XnStreamUncompJPEGContext m_UncompJPEGContext; -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_JPEG_CODEC_H__ +#define __XN_JPEG_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecBase.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API XnJpegCodec : public XnCodecBase +{ +public: + XnJpegCodec(XnBool bRGB, XnUInt32 nXRes, XnUInt32 nYRes, XnUInt32 nQuality = XN_STREAM_COMPRESSION_JPEG_DEFAULT_QUALITY) : + m_bRGB(bRGB), m_nXRes(nXRes), m_nYRes(nYRes), m_nQuality(nQuality) + {} + + ~XnJpegCodec() + { + XnStreamFreeCompressImageJ(&m_CompJPEGContext); + XnStreamFreeUncompressImageJ(&m_UncompJPEGContext); + } + + XnStatus Init() + { + XnStatus nRetVal = XN_STATUS_OK; + + nRetVal = XnStreamInitCompressImageJ(&m_CompJPEGContext); + XN_IS_STATUS_OK(nRetVal); + + nRetVal = XnStreamInitUncompressImageJ(&m_UncompJPEGContext); + if (nRetVal != XN_STATUS_OK) + { + XnStreamFreeCompressImageJ(&m_CompJPEGContext); + return (nRetVal); + } + + return (XN_STATUS_OK); + } + + virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_JPEG; } + virtual XnFloat GetWorseCompressionRatio() const { return XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO; } + virtual XnUInt32 GetOverheadSize() const { return 0; } + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + if (m_bRGB) + { + return XnStreamCompressImage24J(&m_CompJPEGContext, pData, pCompressedData, pnCompressedDataSize, m_nXRes, m_nYRes, m_nQuality); + } + else + { + return XnStreamCompressImage8J(&m_CompJPEGContext, pData, pCompressedData, pnCompressedDataSize, m_nXRes, m_nYRes, m_nQuality); + } + } + + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + return XnStreamUncompressImageJ(&m_UncompJPEGContext, pCompressedData, nCompressedDataSize, pData, pnDataSize); + } + +private: + const XnBool m_bRGB; + const XnUInt32 m_nXRes; + const XnUInt32 m_nYRes; + const XnUInt32 m_nQuality; + XnStreamCompJPEGContext m_CompJPEGContext; + XnStreamUncompJPEGContext m_UncompJPEGContext; +}; + #endif //__XN_JPEG_CODEC_H__ \ No newline at end of file diff --git a/Source/XnFormats/XnNiCodec.h b/Source/XnFormats/XnNiCodec.h index 51b413c..f84c247 100644 --- a/Source/XnFormats/XnNiCodec.h +++ b/Source/XnFormats/XnNiCodec.h @@ -1,63 +1,63 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef __XN_XN_CODEC_H__ -#define __XN_XN_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodec.h" -#include - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API XnNiCodec : public XnCodec -{ -public: - XnNiCodec(xn::Codec& codec) : m_codec(codec) {} - virtual ~XnNiCodec() {} - - virtual XnCompressionFormats GetCompressionFormat() const { return XnCodec::GetCompressionFormatFromCodecID(m_codec.GetCodecID()); } - - virtual XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - return m_codec.EncodeData(pData, nDataSize, pCompressedData, *pnCompressedDataSize, pnCompressedDataSize); - } - - virtual XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - return m_codec.DecodeData(pCompressedData, nCompressedDataSize, pData, *pnDataSize, pnDataSize); - } - -private: - xn::Codec m_codec; -}; - - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef __XN_XN_CODEC_H__ +#define __XN_XN_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodec.h" +#include + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API XnNiCodec : public XnCodec +{ +public: + XnNiCodec(xn::Codec& codec) : m_codec(codec) {} + virtual ~XnNiCodec() {} + + virtual XnCompressionFormats GetCompressionFormat() const { return XnCodec::GetCompressionFormatFromCodecID(m_codec.GetCodecID()); } + + virtual XnStatus Compress(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + return m_codec.EncodeData(pData, nDataSize, pCompressedData, *pnCompressedDataSize, pnCompressedDataSize); + } + + virtual XnStatus Decompress(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + return m_codec.DecodeData(pCompressedData, nCompressedDataSize, pData, *pnDataSize, pnDataSize); + } + +private: + xn::Codec m_codec; +}; + + #endif // __XN_XN_CODEC_H__ \ No newline at end of file diff --git a/Source/XnFormats/XnStreamCompression.cpp b/Source/XnFormats/XnStreamCompression.cpp index aea0a55..a2eb2a3 100644 --- a/Source/XnFormats/XnStreamCompression.cpp +++ b/Source/XnFormats/XnStreamCompression.cpp @@ -1,1275 +1,1275 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnStreamCompression.h" -#include -#include -#include - -//--------------------------------------------------------------------------- -// Code -//--------------------------------------------------------------------------- -XN_FORMATS_API XnStatus XnStreamCompressDepth16Z(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt16* pInputEnd = pInput + (nInputSize / sizeof(XnUInt16)); - XnUInt8* pOrigOutput = pOutput; - XnUInt16 nCurrValue = 0; - XnUInt16 nLastValue = 0; - XnUInt16 nAbsDiffValue = 0; - XnInt16 nDiffValue = 0; - XnUInt8 cOutStage = 0; - XnUInt8 cOutChar = 0; - XnUInt8 cZeroCounter = 0; - - // Note: this function does not make sure it stay within the output memory boundaries! - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - if (nInputSize == 0) - { - *pnOutputSize = 0; - return XN_STATUS_OK; - } - - // Encode the data... - nLastValue = *pInput; - *(XnUInt16*)pOutput = nLastValue; - pInput++; - pOutput+=2; - - while (pInput != pInputEnd) - { - nCurrValue = *pInput; - - nDiffValue = (nLastValue - nCurrValue); - nAbsDiffValue = abs(nDiffValue); - - if (nAbsDiffValue <= 6) - { - nDiffValue += 6; - - if (cOutStage == 0) - { - cOutChar = nDiffValue << 4; - - cOutStage = 1; - } - else - { - cOutChar += nDiffValue; - - if (cOutChar == 0x66) - { - cZeroCounter++; - - if (cZeroCounter == 15) - { - *pOutput = 0xEF; - pOutput++; - - cZeroCounter = 0; - } - } - else - { - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - - cZeroCounter = 0; - } - - *pOutput = cOutChar; - pOutput++; - } - - cOutStage = 0; - } - } - else - { - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - - cZeroCounter = 0; - } - - if (cOutStage == 0) - { - cOutChar = 0xFF; - } - else - { - cOutChar += 0x0F; - cOutStage = 0; - } - - *pOutput = cOutChar; - pOutput++; - - if (nAbsDiffValue <= 63) - { - nDiffValue += 192; - - *pOutput = nDiffValue; - pOutput++; - } - else - { - *(XnUInt16*)pOutput = (nCurrValue << 8) + (nCurrValue >> 8); - pOutput+=2; - } - } - - nLastValue = nCurrValue; - pInput++; - } - - if (cOutStage != 0) - { - *pOutput = cOutChar + 0x0D; - pOutput++; - } - - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - } - - *pnOutputSize = pOutput - pOrigOutput; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamCompressDepth16ZWithEmbTable(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nMaxValue) -{ - // Local function variables - const XnUInt16* pInputEnd = pInput + (nInputSize / sizeof(XnUInt16)); - const XnUInt16* pOrigInput = pInput; - const XnUInt8* pOrigOutput = pOutput; - XnUInt16 nCurrValue = 0; - XnUInt16 nLastValue = 0; - XnUInt16 nAbsDiffValue = 0; - XnInt16 nDiffValue = 0; - XnUInt8 cOutStage = 0; - XnUInt8 cOutChar = 0; - XnUInt8 cZeroCounter = 0; - static XnUInt16 nEmbTable[XN_MAX_UINT16]; - XnUInt16 nEmbTableIdx=0; - - // Note: this function does not make sure it stay within the output memory boundaries! - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - // Create the embedded value translation table... - pOutput+=2; - xnOSMemSet(&nEmbTable[0], 0, nMaxValue*sizeof(XnUInt16)); - - while (pInput != pInputEnd) - { - nEmbTable[*pInput] = 1; - pInput++; - } - - for (XnUInt32 i=0; i> 8)); - pOutput+=2; - } - } - - nLastValue = nCurrValue; - pInput++; - } - - if (cOutStage != 0) - { - *pOutput = cOutChar + 0x0D; - pOutput++; - } - - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - } - - *pnOutputSize = pOutput - pOrigOutput; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamUncompressDepth16Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt8* pInputEnd = pInput + nInputSize; - XnUInt16* pOutputEnd = 0; - const XnUInt16* pOrigOutput = pOutput; - XnUInt16 nLastFullValue = 0; - XnUInt8 cInput = 0; - XnUInt8 cZeroCounter = 0; - XnInt8 cInData1 = 0; - XnInt8 cInData2 = 0; - XnUInt8 cInData3 = 0; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - if (nInputSize < sizeof(XnUInt16)) - { - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); - - // Decode the data... - nLastFullValue = *(XnUInt16*)pInput; - *pOutput = nLastFullValue; - pInput+=2; - pOutput++; - - while (pInput != pInputEnd) - { - cInput = *pInput; - - if (cInput < 0xE0) - { - cInData1 = cInput >> 4; - cInData2 = (cInput & 0x0f); - - nLastFullValue -= (cInData1 - 6); - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - pOutput++; - - if (cInData2 != 0x0f) - { - if (cInData2 != 0x0d) - { - nLastFullValue -= (cInData2 - 6); - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - pOutput++; - } - - pInput++; - } - else - { - pInput++; - - cInData3 = *pInput; - if (cInData3 & 0x80) - { - nLastFullValue -= (cInData3 - 192); - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - - pOutput++; - pInput++; - } - else - { - nLastFullValue = cInData3 << 8; - pInput++; - nLastFullValue += *pInput; - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - - pOutput++; - pInput++; - } - } - } - else if (cInput == 0xFF) - { - pInput++; - - cInData3 = *pInput; - - if (cInData3 & 0x80) - { - nLastFullValue -= (cInData3 - 192); - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - - pInput++; - pOutput++; - } - else - { - nLastFullValue = cInData3 << 8; - pInput++; - nLastFullValue += *pInput; - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = nLastFullValue; - - pInput++; - pOutput++; - } - } - else //It must be 0xE? - { - cZeroCounter = cInput - 0xE0; - - while (cZeroCounter != 0) - { - XN_CHECK_OUTPUT_OVERFLOW(pOutput+1, pOutputEnd); - *pOutput = nLastFullValue; - pOutput++; - - *pOutput = nLastFullValue; - pOutput++; - - cZeroCounter--; - } - - pInput++; - } - } - - *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt16); - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamUncompressDepth16ZWithEmbTable(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt8* pInputEnd = pInput + nInputSize; - XnUInt16* pOutputEnd = 0; - XnUInt16* pOrigOutput = pOutput; - XnUInt16 nLastFullValue = 0; - XnUInt8 cInput = 0; - XnUInt8 cZeroCounter = 0; - XnInt8 cInData1 = 0; - XnInt8 cInData2 = 0; - XnUInt8 cInData3 = 0; - XnUInt16* pEmbTable = NULL; - XnUInt16 nEmbTableIdx = 0; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - if (nInputSize < sizeof(XnUInt16)) - { - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - nEmbTableIdx = XN_PREPARE_VAR16_IN_BUFFER(*(XnUInt16*)pInput); - pInput+=2; - pEmbTable = (XnUInt16*)pInput; - pInput+=nEmbTableIdx * 2; - for (XnUInt32 i = 0; i < nEmbTableIdx; i++) - pEmbTable[i] = XN_PREPARE_VAR16_IN_BUFFER(pEmbTable[i]); - - pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); - - // Decode the data... - nLastFullValue = XN_PREPARE_VAR16_IN_BUFFER(*(XnUInt16*)pInput); - *pOutput = pEmbTable[nLastFullValue]; - pInput+=2; - pOutput++; - - while (pInput != pInputEnd) - { - cInput = *pInput; - - if (cInput < 0xE0) - { - cInData1 = cInput >> 4; - cInData2 = (cInput & 0x0f); - - nLastFullValue -= (cInData1 - 6); - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - pOutput++; - - if (cInData2 != 0x0f) - { - if (cInData2 != 0x0d) - { - nLastFullValue -= (cInData2 - 6); - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - pOutput++; - } - - pInput++; - } - else - { - pInput++; - - cInData3 = *pInput; - if (cInData3 & 0x80) - { - nLastFullValue -= (cInData3 - 192); - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - - pOutput++; - pInput++; - } - else - { - nLastFullValue = cInData3 << 8; - pInput++; - nLastFullValue += *pInput; - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - - pOutput++; - pInput++; - } - } - } - else if (cInput == 0xFF) - { - pInput++; - - cInData3 = *pInput; - - if (cInData3 & 0x80) - { - nLastFullValue -= (cInData3 - 192); - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - - pInput++; - pOutput++; - } - else - { - nLastFullValue = cInData3 << 8; - pInput++; - nLastFullValue += *pInput; - - XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - - pInput++; - pOutput++; - } - } - else //It must be 0xE? - { - cZeroCounter = cInput - 0xE0; - - while (cZeroCounter != 0) - { - XN_CHECK_OUTPUT_OVERFLOW(pOutput+1, pOutputEnd); - *pOutput = pEmbTable[nLastFullValue]; - pOutput++; - - *pOutput = pEmbTable[nLastFullValue]; - pOutput++; - - cZeroCounter--; - } - - pInput++; - } - } - - *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt16); - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamCompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt8* pInputEnd = pInput + nInputSize; - const XnUInt8* pOrigOutput = pOutput; - XnUInt8 nCurrValue = 0; - XnUInt8 nLastValue = 0; - XnUInt8 nAbsDiffValue = 0; - XnInt8 nDiffValue = 0; - XnUInt8 cOutStage = 0; - XnUInt8 cOutChar = 0; - XnUInt8 cZeroCounter = 0; - XnBool bFlag = FALSE; - - // Note: this function does not make sure it stay within the output memory boundaries! - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - // Encode the data... - nLastValue = *pInput; - *pOutput = nLastValue; - pInput++; - pOutput++; - - while (pInput != pInputEnd) - { - nCurrValue = *pInput; - - nDiffValue = (nLastValue - nCurrValue); - nAbsDiffValue = abs(nDiffValue); - - if (nAbsDiffValue <= 6) - { - nDiffValue += 6; - - if (cOutStage == 0) - { - cOutChar = nDiffValue << 4; - - cOutStage = 1; - } - else - { - cOutChar += nDiffValue; - - if ((cOutChar == 0x66) && (bFlag == FALSE)) - { - cZeroCounter++; - - if (cZeroCounter == 15) - { - *pOutput = 0xEF; - pOutput++; - - cZeroCounter = 0; - } - } - else - { - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - - cZeroCounter = 0; - } - - *pOutput = cOutChar; - pOutput++; - - bFlag = FALSE; - } - - cOutStage = 0; - } - } - else - { - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - - cZeroCounter = 0; - } - - if (cOutStage == 0) - { - cOutChar = 0xF0; - cOutChar += nCurrValue >> 4; - - *pOutput = cOutChar; - pOutput++; - - cOutChar = (nCurrValue & 0xF) << 4; - cOutStage = 1; - - bFlag = TRUE; - } - else - { - cOutChar += 0x0F; - cOutStage = 0; - - *pOutput = cOutChar; - pOutput++; - - *pOutput = nCurrValue; - pOutput++; - } - } - - nLastValue = nCurrValue; - pInput++; - } - - if (cOutStage != 0) - { - *pOutput = cOutChar + 0x0D; - pOutput++; - } - - if (cZeroCounter != 0) - { - *pOutput = 0xE0 + cZeroCounter; - pOutput++; - } - - *pnOutputSize = pOutput - pOrigOutput; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamUncompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - const XnUInt8* pInputEnd = pInput + nInputSize; - const XnUInt8* pOrigOutput = pOutput; - XnUInt8 nLastFullValue = 0; - XnUInt8 cInput = 0; - XnUInt8 cZeroCounter = 0; - XnInt8 cInData1 = 0; - XnInt8 cInData2 = 0; - - // Note: this function does not make sure it stay within the output memory boundaries! - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - if (nInputSize < sizeof(XnUInt8)) - { - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - // Decode the data... - nLastFullValue = *pInput; - *pOutput = nLastFullValue; - pInput++; - pOutput++; - - while (pInput != pInputEnd) - { - cInput = *pInput; - - if (cInput < 0xE0) - { - cInData1 = cInput >> 4; - cInData2 = (cInput & 0x0f); - - nLastFullValue -= (cInData1 - 6); - *pOutput = nLastFullValue; - pOutput++; - - if (cInData2 != 0x0f) - { - if (cInData2 != 0x0d) - { - nLastFullValue -= (cInData2 - 6); - *pOutput = nLastFullValue; - pOutput++; - } - } - else - { - pInput++; - nLastFullValue = *pInput; - *pOutput = nLastFullValue; - pOutput++; - } - - pInput++; - } - else if (cInput >= 0xF0) - { - cInData1 = cInput << 4; - - pInput++; - cInput = *pInput; - - nLastFullValue = cInData1 + (cInput >> 4); - - *pOutput = nLastFullValue; - pOutput++; - - cInData2 = cInput & 0xF; - - if (cInData2 == 0x0F) - { - pInput++; - nLastFullValue = *pInput; - *pOutput = nLastFullValue; - pOutput++; - pInput++; - } - else - { - if (cInData2 != 0x0D) - { - nLastFullValue -= (cInData2 - 6); - *pOutput = nLastFullValue; - pOutput++; - } - - pInput++; - } - } - else //It must be 0xE? - { - cZeroCounter = cInput - 0xE0; - - while (cZeroCounter != 0) - { - *pOutput = nLastFullValue; - pOutput++; - - *pOutput = nLastFullValue; - pOutput++; - - cZeroCounter--; - } - - pInput++; - } - } - - *pnOutputSize = (pOutput - pOrigOutput); - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamCompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt8* pInputEnd = pInput + nInputSize; - const XnUInt8* pOrigOutput = pOutput; - - // Note: this function does not make sure it stay within the output memory boundaries! - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - // Encode the data... - while (pInput != pInputEnd) - { - *pOutput = *pInput << 4; - pInput++; - - *pOutput += *pInput; - pInput++; - - pOutput++; - } - - *pnOutputSize = pOutput - pOrigOutput; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamUncompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - const XnUInt8* pInputEnd = pInput + nInputSize; - const XnUInt8* pOutputEnd = 0; - const XnUInt8* pOrigOutput = pOutput; - XnUInt8 nValue1; - XnUInt8 nValue2; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_INPUT_PTR(pOutput); - XN_VALIDATE_INPUT_PTR(pnOutputSize); - - if (nInputSize < sizeof(XnUInt8)) - { - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - if (nInputSize % 2 != 0) - { - return (XN_STATUS_IO_INVALID_COMPRESSED_BUFFER_SIZE); - } - - pOutputEnd = pOutput + *pnOutputSize; - - XN_CHECK_OUTPUT_OVERFLOW(pOutput + (nInputSize * 2), pOutputEnd); - - while (pInput != pInputEnd) - { - nValue1 = pInput[0]; - nValue2 = pInput[1]; - - pOutput[0] = nValue1 >> 4; - pOutput[1] = nValue1 & 0xF; - pOutput[2] = nValue2 >> 4; - pOutput[3] = nValue2 & 0xF; - - pOutput+=4; - pInput+=2; - } - - *pnOutputSize = (pOutput - pOrigOutput); - - // All is good... - return (XN_STATUS_OK); -} - -void XnStreamJPEGCompDummyFunction(struct jpeg_compress_struct* pjCompStruct) -{ - // Dummy libjpeg function to wrap internal buffers usage... -} - -boolean XnStreamJPEGCompDummyFailFunction(struct jpeg_compress_struct* pjCompStruct) -{ - // If we ever got to the point we need to allocate more memory, something is wrong! - return (FALSE); -} - -XN_FORMATS_API XnStatus XnStreamInitCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_OUTPUT_PTR(pStreamCompJPEGContext); - - pStreamCompJPEGContext->jCompStruct.err = jpeg_std_error(&pStreamCompJPEGContext->jErrMgr); - - jpeg_create_compress(&pStreamCompJPEGContext->jCompStruct); - - pStreamCompJPEGContext->jCompStruct.dest = &pStreamCompJPEGContext->jDestMgr; - pStreamCompJPEGContext->jCompStruct.dest->init_destination = XnStreamJPEGCompDummyFunction; - pStreamCompJPEGContext->jCompStruct.dest->empty_output_buffer = XnStreamJPEGCompDummyFailFunction; - pStreamCompJPEGContext->jCompStruct.dest->term_destination = XnStreamJPEGCompDummyFunction; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamFreeCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); - - jpeg_destroy_compress(&pStreamCompJPEGContext->jCompStruct); - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamCompressImage8J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality) -{ - // Local function variables - XnUInt8* pCurrScanline = (XnUInt8*)pInput; - XnUInt32 nYIndex = 0; - jpeg_compress_struct* pjCompStruct = NULL; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_OUTPUT_PTR(pOutput); - XN_VALIDATE_OUTPUT_PTR(pnOutputSize); - - pjCompStruct = &pStreamCompJPEGContext->jCompStruct; - - pjCompStruct->in_color_space = JCS_GRAYSCALE; - jpeg_set_defaults(pjCompStruct); - pjCompStruct->input_components = 1; - pjCompStruct->num_components = 1; - pjCompStruct->image_width = nXRes; - pjCompStruct->image_height = nYRes; - pjCompStruct->data_precision = 8; - pjCompStruct->input_gamma = 1.0; - - jpeg_set_quality(pjCompStruct, nQuality, FALSE); - - pjCompStruct->dest->next_output_byte = (JOCTET*)pOutput; - pjCompStruct->dest->free_in_buffer = *pnOutputSize; - - jpeg_start_compress(pjCompStruct, TRUE); - - for (nYIndex = 0; nYIndex < nYRes; nYIndex++) - { - jpeg_write_scanlines(pjCompStruct, &pCurrScanline, 1); - - pCurrScanline += nXRes; - } - - jpeg_finish_compress(pjCompStruct); - - *pnOutputSize -= pjCompStruct->dest->free_in_buffer; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamCompressImage24J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality) -{ - // Local function variables - XnUInt8* pCurrScanline = (XnUChar*)pInput; - XnUInt32 nYIndex = 0; - XnUInt32 nScanLineSize = 0; - jpeg_compress_struct* pjCompStruct = NULL; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_OUTPUT_PTR(pOutput); - XN_VALIDATE_OUTPUT_PTR(pnOutputSize); - - pjCompStruct = &pStreamCompJPEGContext->jCompStruct; - - pjCompStruct->in_color_space = JCS_RGB; - jpeg_set_defaults(pjCompStruct); - pjCompStruct->input_components = 3; - pjCompStruct->num_components = 3; - pjCompStruct->image_width = nXRes; - pjCompStruct->image_height = nYRes; - pjCompStruct->data_precision = 8; - pjCompStruct->input_gamma = 1.0; - - jpeg_set_quality(pjCompStruct, nQuality, FALSE); - - pjCompStruct->dest->next_output_byte = (JOCTET*)pOutput; - pjCompStruct->dest->free_in_buffer = *pnOutputSize; - - jpeg_start_compress(pjCompStruct, TRUE); - - nScanLineSize = nXRes * 3; - for (nYIndex = 0; nYIndex < nYRes; nYIndex++) - { - jpeg_write_scanlines(pjCompStruct, &pCurrScanline, 1); - - pCurrScanline += nScanLineSize; - } - - jpeg_finish_compress(pjCompStruct); - - *pnOutputSize -= pjCompStruct->dest->free_in_buffer; - - // All is good... - return (XN_STATUS_OK); -} - -void XnStreamJPEGDecompDummyFunction(struct jpeg_decompress_struct* pjDecompStruct) -{ - // Dummy libjpeg function to wrap internal buffers usage... -} - -boolean XnStreamJPEGDecompDummyFailFunction(struct jpeg_decompress_struct* pjDecompStruct) -{ - // If we ever got to the point we need to allocate more memory, something is wrong! - return (FALSE); -} - -void XnStreamJPEGDecompSkipFunction(struct jpeg_decompress_struct* pjDecompStruct, long nNumBytes) -{ - // Skip bytes in the internal buffer - pjDecompStruct->src->next_input_byte += (size_t)nNumBytes; - pjDecompStruct->src->bytes_in_buffer -= (size_t)nNumBytes; -} - -void XnStreamJPEGDummyErrorExit(j_common_ptr cinfo) -{ - XnLibJpegErrorMgr* errMgr = (XnLibJpegErrorMgr*)cinfo->err; - - longjmp(errMgr->setjmpBuffer, 1); -} - -void XnStreamJPEGOutputMessage(j_common_ptr cinfo) -{ - struct jpeg_error_mgr* err = cinfo->err; - int msg_code = err->msg_code; - if (msg_code == JWRN_EXTRANEOUS_DATA) - { - // NOTE: we are aware this problem occurs. Log a warning every once in a while - static XnUInt32 nTimes = 0; - if (++nTimes == 50) - { - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - //Temporary disabled this error since it happens all the time and it's a known issue. - //xnLogWarning(XN_MASK_JPEG, "JPEG: The following warning occurred 50 times: %s", buffer); - nTimes = 0; - } - } - else - { - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - xnLogWarning(XN_MASK_JPEG, "JPEG: %s", buffer); - } -} - -XN_FORMATS_API XnStatus XnStreamInitUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_OUTPUT_PTR(pStreamUncompJPEGContext); - - pStreamUncompJPEGContext->jDecompStruct.err = jpeg_std_error(&pStreamUncompJPEGContext->jErrMgr.pub); - pStreamUncompJPEGContext->jErrMgr.pub.output_message = XnStreamJPEGOutputMessage; - pStreamUncompJPEGContext->jErrMgr.pub.error_exit = XnStreamJPEGDummyErrorExit; - - jpeg_create_decompress(&pStreamUncompJPEGContext->jDecompStruct); - - pStreamUncompJPEGContext->jDecompStruct.src = &pStreamUncompJPEGContext->jSrcMgr; - pStreamUncompJPEGContext->jDecompStruct.src->init_source = XnStreamJPEGDecompDummyFunction; - pStreamUncompJPEGContext->jDecompStruct.src->fill_input_buffer = XnStreamJPEGDecompDummyFailFunction; - pStreamUncompJPEGContext->jDecompStruct.src->skip_input_data = XnStreamJPEGDecompSkipFunction; - pStreamUncompJPEGContext->jDecompStruct.src->resync_to_restart = jpeg_resync_to_restart; - pStreamUncompJPEGContext->jDecompStruct.src->term_source = XnStreamJPEGDecompDummyFunction; - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamFreeUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext) -{ - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pStreamUncompJPEGContext); - - jpeg_destroy_decompress(&pStreamUncompJPEGContext->jDecompStruct); - - // All is good... - return (XN_STATUS_OK); -} - -XN_FORMATS_API XnStatus XnStreamUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext, const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) -{ - // Local function variables - XnUInt8* pCurrScanline = pOutput; - XnUInt8* pNextScanline = NULL; - XnUInt8* pOutputEnd = 0; - XnUInt32 nScanLineSize = 0; - XnUInt32 nOutputSize = 0; - jpeg_decompress_struct* pjDecompStruct = NULL; - - // Validate the input/output pointers (to make sure none of them is NULL) - XN_VALIDATE_INPUT_PTR(pStreamUncompJPEGContext); - XN_VALIDATE_INPUT_PTR(pInput); - XN_VALIDATE_OUTPUT_PTR(pOutput); - XN_VALIDATE_OUTPUT_PTR(pnOutputSize); - - if (nInputSize == 0) - { - return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); - } - - pOutputEnd = pOutput + *pnOutputSize; - - pjDecompStruct = &pStreamUncompJPEGContext->jDecompStruct; - - pjDecompStruct->src->bytes_in_buffer = nInputSize; - pjDecompStruct->src->next_input_byte = pInput; - - if (setjmp(pStreamUncompJPEGContext->jErrMgr.setjmpBuffer)) - { - //If we get here, the JPEG code has signaled an error. - XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); - XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); - - *pnOutputSize = 0; - - return (XN_STATUS_IO_DECOMPRESSION_FAILED); - } - - jpeg_read_header(pjDecompStruct, TRUE); - - jpeg_start_decompress(pjDecompStruct); - - nScanLineSize = pjDecompStruct->output_width * pjDecompStruct->num_components; - - nOutputSize = pjDecompStruct->output_height * nScanLineSize; - if (nOutputSize > *pnOutputSize) - { - XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); - XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); - - *pnOutputSize = 0; - - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - while (pStreamUncompJPEGContext->jDecompStruct.output_scanline < pStreamUncompJPEGContext->jDecompStruct.output_height) - { - pNextScanline = pCurrScanline+nScanLineSize; - - if (pNextScanline > pOutputEnd) - { - XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); - XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); - - *pnOutputSize = 0; - - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - jpeg_read_scanlines(pjDecompStruct, &pCurrScanline, 1); - pCurrScanline = pNextScanline; - } - - jpeg_finish_decompress(pjDecompStruct); - - *pnOutputSize = nOutputSize; - - // All is good... - return (XN_STATUS_OK); -} +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnStreamCompression.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// Code +//--------------------------------------------------------------------------- +XN_FORMATS_API XnStatus XnStreamCompressDepth16Z(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt16* pInputEnd = pInput + (nInputSize / sizeof(XnUInt16)); + XnUInt8* pOrigOutput = pOutput; + XnUInt16 nCurrValue = 0; + XnUInt16 nLastValue = 0; + XnUInt16 nAbsDiffValue = 0; + XnInt16 nDiffValue = 0; + XnUInt8 cOutStage = 0; + XnUInt8 cOutChar = 0; + XnUInt8 cZeroCounter = 0; + + // Note: this function does not make sure it stay within the output memory boundaries! + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + if (nInputSize == 0) + { + *pnOutputSize = 0; + return XN_STATUS_OK; + } + + // Encode the data... + nLastValue = *pInput; + *(XnUInt16*)pOutput = nLastValue; + pInput++; + pOutput+=2; + + while (pInput != pInputEnd) + { + nCurrValue = *pInput; + + nDiffValue = (nLastValue - nCurrValue); + nAbsDiffValue = abs(nDiffValue); + + if (nAbsDiffValue <= 6) + { + nDiffValue += 6; + + if (cOutStage == 0) + { + cOutChar = nDiffValue << 4; + + cOutStage = 1; + } + else + { + cOutChar += nDiffValue; + + if (cOutChar == 0x66) + { + cZeroCounter++; + + if (cZeroCounter == 15) + { + *pOutput = 0xEF; + pOutput++; + + cZeroCounter = 0; + } + } + else + { + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + + cZeroCounter = 0; + } + + *pOutput = cOutChar; + pOutput++; + } + + cOutStage = 0; + } + } + else + { + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + + cZeroCounter = 0; + } + + if (cOutStage == 0) + { + cOutChar = 0xFF; + } + else + { + cOutChar += 0x0F; + cOutStage = 0; + } + + *pOutput = cOutChar; + pOutput++; + + if (nAbsDiffValue <= 63) + { + nDiffValue += 192; + + *pOutput = nDiffValue; + pOutput++; + } + else + { + *(XnUInt16*)pOutput = (nCurrValue << 8) + (nCurrValue >> 8); + pOutput+=2; + } + } + + nLastValue = nCurrValue; + pInput++; + } + + if (cOutStage != 0) + { + *pOutput = cOutChar + 0x0D; + pOutput++; + } + + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + } + + *pnOutputSize = pOutput - pOrigOutput; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamCompressDepth16ZWithEmbTable(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nMaxValue) +{ + // Local function variables + const XnUInt16* pInputEnd = pInput + (nInputSize / sizeof(XnUInt16)); + const XnUInt16* pOrigInput = pInput; + const XnUInt8* pOrigOutput = pOutput; + XnUInt16 nCurrValue = 0; + XnUInt16 nLastValue = 0; + XnUInt16 nAbsDiffValue = 0; + XnInt16 nDiffValue = 0; + XnUInt8 cOutStage = 0; + XnUInt8 cOutChar = 0; + XnUInt8 cZeroCounter = 0; + static XnUInt16 nEmbTable[XN_MAX_UINT16]; + XnUInt16 nEmbTableIdx=0; + + // Note: this function does not make sure it stay within the output memory boundaries! + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + // Create the embedded value translation table... + pOutput+=2; + xnOSMemSet(&nEmbTable[0], 0, nMaxValue*sizeof(XnUInt16)); + + while (pInput != pInputEnd) + { + nEmbTable[*pInput] = 1; + pInput++; + } + + for (XnUInt32 i=0; i> 8)); + pOutput+=2; + } + } + + nLastValue = nCurrValue; + pInput++; + } + + if (cOutStage != 0) + { + *pOutput = cOutChar + 0x0D; + pOutput++; + } + + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + } + + *pnOutputSize = pOutput - pOrigOutput; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamUncompressDepth16Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt8* pInputEnd = pInput + nInputSize; + XnUInt16* pOutputEnd = 0; + const XnUInt16* pOrigOutput = pOutput; + XnUInt16 nLastFullValue = 0; + XnUInt8 cInput = 0; + XnUInt8 cZeroCounter = 0; + XnInt8 cInData1 = 0; + XnInt8 cInData2 = 0; + XnUInt8 cInData3 = 0; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + if (nInputSize < sizeof(XnUInt16)) + { + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); + + // Decode the data... + nLastFullValue = *(XnUInt16*)pInput; + *pOutput = nLastFullValue; + pInput+=2; + pOutput++; + + while (pInput != pInputEnd) + { + cInput = *pInput; + + if (cInput < 0xE0) + { + cInData1 = cInput >> 4; + cInData2 = (cInput & 0x0f); + + nLastFullValue -= (cInData1 - 6); + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + pOutput++; + + if (cInData2 != 0x0f) + { + if (cInData2 != 0x0d) + { + nLastFullValue -= (cInData2 - 6); + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + pOutput++; + } + + pInput++; + } + else + { + pInput++; + + cInData3 = *pInput; + if (cInData3 & 0x80) + { + nLastFullValue -= (cInData3 - 192); + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + + pOutput++; + pInput++; + } + else + { + nLastFullValue = cInData3 << 8; + pInput++; + nLastFullValue += *pInput; + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + + pOutput++; + pInput++; + } + } + } + else if (cInput == 0xFF) + { + pInput++; + + cInData3 = *pInput; + + if (cInData3 & 0x80) + { + nLastFullValue -= (cInData3 - 192); + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + + pInput++; + pOutput++; + } + else + { + nLastFullValue = cInData3 << 8; + pInput++; + nLastFullValue += *pInput; + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = nLastFullValue; + + pInput++; + pOutput++; + } + } + else //It must be 0xE? + { + cZeroCounter = cInput - 0xE0; + + while (cZeroCounter != 0) + { + XN_CHECK_OUTPUT_OVERFLOW(pOutput+1, pOutputEnd); + *pOutput = nLastFullValue; + pOutput++; + + *pOutput = nLastFullValue; + pOutput++; + + cZeroCounter--; + } + + pInput++; + } + } + + *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt16); + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamUncompressDepth16ZWithEmbTable(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt8* pInputEnd = pInput + nInputSize; + XnUInt16* pOutputEnd = 0; + XnUInt16* pOrigOutput = pOutput; + XnUInt16 nLastFullValue = 0; + XnUInt8 cInput = 0; + XnUInt8 cZeroCounter = 0; + XnInt8 cInData1 = 0; + XnInt8 cInData2 = 0; + XnUInt8 cInData3 = 0; + XnUInt16* pEmbTable = NULL; + XnUInt16 nEmbTableIdx = 0; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + if (nInputSize < sizeof(XnUInt16)) + { + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + nEmbTableIdx = XN_PREPARE_VAR16_IN_BUFFER(*(XnUInt16*)pInput); + pInput+=2; + pEmbTable = (XnUInt16*)pInput; + pInput+=nEmbTableIdx * 2; + for (XnUInt32 i = 0; i < nEmbTableIdx; i++) + pEmbTable[i] = XN_PREPARE_VAR16_IN_BUFFER(pEmbTable[i]); + + pOutputEnd = pOutput + (*pnOutputSize / sizeof(XnUInt16)); + + // Decode the data... + nLastFullValue = XN_PREPARE_VAR16_IN_BUFFER(*(XnUInt16*)pInput); + *pOutput = pEmbTable[nLastFullValue]; + pInput+=2; + pOutput++; + + while (pInput != pInputEnd) + { + cInput = *pInput; + + if (cInput < 0xE0) + { + cInData1 = cInput >> 4; + cInData2 = (cInput & 0x0f); + + nLastFullValue -= (cInData1 - 6); + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + pOutput++; + + if (cInData2 != 0x0f) + { + if (cInData2 != 0x0d) + { + nLastFullValue -= (cInData2 - 6); + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + pOutput++; + } + + pInput++; + } + else + { + pInput++; + + cInData3 = *pInput; + if (cInData3 & 0x80) + { + nLastFullValue -= (cInData3 - 192); + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + + pOutput++; + pInput++; + } + else + { + nLastFullValue = cInData3 << 8; + pInput++; + nLastFullValue += *pInput; + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + + pOutput++; + pInput++; + } + } + } + else if (cInput == 0xFF) + { + pInput++; + + cInData3 = *pInput; + + if (cInData3 & 0x80) + { + nLastFullValue -= (cInData3 - 192); + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + + pInput++; + pOutput++; + } + else + { + nLastFullValue = cInData3 << 8; + pInput++; + nLastFullValue += *pInput; + + XN_CHECK_OUTPUT_OVERFLOW(pOutput, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + + pInput++; + pOutput++; + } + } + else //It must be 0xE? + { + cZeroCounter = cInput - 0xE0; + + while (cZeroCounter != 0) + { + XN_CHECK_OUTPUT_OVERFLOW(pOutput+1, pOutputEnd); + *pOutput = pEmbTable[nLastFullValue]; + pOutput++; + + *pOutput = pEmbTable[nLastFullValue]; + pOutput++; + + cZeroCounter--; + } + + pInput++; + } + } + + *pnOutputSize = (pOutput - pOrigOutput) * sizeof(XnUInt16); + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamCompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt8* pInputEnd = pInput + nInputSize; + const XnUInt8* pOrigOutput = pOutput; + XnUInt8 nCurrValue = 0; + XnUInt8 nLastValue = 0; + XnUInt8 nAbsDiffValue = 0; + XnInt8 nDiffValue = 0; + XnUInt8 cOutStage = 0; + XnUInt8 cOutChar = 0; + XnUInt8 cZeroCounter = 0; + XnBool bFlag = FALSE; + + // Note: this function does not make sure it stay within the output memory boundaries! + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + // Encode the data... + nLastValue = *pInput; + *pOutput = nLastValue; + pInput++; + pOutput++; + + while (pInput != pInputEnd) + { + nCurrValue = *pInput; + + nDiffValue = (nLastValue - nCurrValue); + nAbsDiffValue = abs(nDiffValue); + + if (nAbsDiffValue <= 6) + { + nDiffValue += 6; + + if (cOutStage == 0) + { + cOutChar = nDiffValue << 4; + + cOutStage = 1; + } + else + { + cOutChar += nDiffValue; + + if ((cOutChar == 0x66) && (bFlag == FALSE)) + { + cZeroCounter++; + + if (cZeroCounter == 15) + { + *pOutput = 0xEF; + pOutput++; + + cZeroCounter = 0; + } + } + else + { + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + + cZeroCounter = 0; + } + + *pOutput = cOutChar; + pOutput++; + + bFlag = FALSE; + } + + cOutStage = 0; + } + } + else + { + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + + cZeroCounter = 0; + } + + if (cOutStage == 0) + { + cOutChar = 0xF0; + cOutChar += nCurrValue >> 4; + + *pOutput = cOutChar; + pOutput++; + + cOutChar = (nCurrValue & 0xF) << 4; + cOutStage = 1; + + bFlag = TRUE; + } + else + { + cOutChar += 0x0F; + cOutStage = 0; + + *pOutput = cOutChar; + pOutput++; + + *pOutput = nCurrValue; + pOutput++; + } + } + + nLastValue = nCurrValue; + pInput++; + } + + if (cOutStage != 0) + { + *pOutput = cOutChar + 0x0D; + pOutput++; + } + + if (cZeroCounter != 0) + { + *pOutput = 0xE0 + cZeroCounter; + pOutput++; + } + + *pnOutputSize = pOutput - pOrigOutput; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamUncompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + const XnUInt8* pInputEnd = pInput + nInputSize; + const XnUInt8* pOrigOutput = pOutput; + XnUInt8 nLastFullValue = 0; + XnUInt8 cInput = 0; + XnUInt8 cZeroCounter = 0; + XnInt8 cInData1 = 0; + XnInt8 cInData2 = 0; + + // Note: this function does not make sure it stay within the output memory boundaries! + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + if (nInputSize < sizeof(XnUInt8)) + { + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + // Decode the data... + nLastFullValue = *pInput; + *pOutput = nLastFullValue; + pInput++; + pOutput++; + + while (pInput != pInputEnd) + { + cInput = *pInput; + + if (cInput < 0xE0) + { + cInData1 = cInput >> 4; + cInData2 = (cInput & 0x0f); + + nLastFullValue -= (cInData1 - 6); + *pOutput = nLastFullValue; + pOutput++; + + if (cInData2 != 0x0f) + { + if (cInData2 != 0x0d) + { + nLastFullValue -= (cInData2 - 6); + *pOutput = nLastFullValue; + pOutput++; + } + } + else + { + pInput++; + nLastFullValue = *pInput; + *pOutput = nLastFullValue; + pOutput++; + } + + pInput++; + } + else if (cInput >= 0xF0) + { + cInData1 = cInput << 4; + + pInput++; + cInput = *pInput; + + nLastFullValue = cInData1 + (cInput >> 4); + + *pOutput = nLastFullValue; + pOutput++; + + cInData2 = cInput & 0xF; + + if (cInData2 == 0x0F) + { + pInput++; + nLastFullValue = *pInput; + *pOutput = nLastFullValue; + pOutput++; + pInput++; + } + else + { + if (cInData2 != 0x0D) + { + nLastFullValue -= (cInData2 - 6); + *pOutput = nLastFullValue; + pOutput++; + } + + pInput++; + } + } + else //It must be 0xE? + { + cZeroCounter = cInput - 0xE0; + + while (cZeroCounter != 0) + { + *pOutput = nLastFullValue; + pOutput++; + + *pOutput = nLastFullValue; + pOutput++; + + cZeroCounter--; + } + + pInput++; + } + } + + *pnOutputSize = (pOutput - pOrigOutput); + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamCompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt8* pInputEnd = pInput + nInputSize; + const XnUInt8* pOrigOutput = pOutput; + + // Note: this function does not make sure it stay within the output memory boundaries! + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + // Encode the data... + while (pInput != pInputEnd) + { + *pOutput = *pInput << 4; + pInput++; + + *pOutput += *pInput; + pInput++; + + pOutput++; + } + + *pnOutputSize = pOutput - pOrigOutput; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamUncompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + const XnUInt8* pInputEnd = pInput + nInputSize; + const XnUInt8* pOutputEnd = 0; + const XnUInt8* pOrigOutput = pOutput; + XnUInt8 nValue1; + XnUInt8 nValue2; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_INPUT_PTR(pOutput); + XN_VALIDATE_INPUT_PTR(pnOutputSize); + + if (nInputSize < sizeof(XnUInt8)) + { + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + if (nInputSize % 2 != 0) + { + return (XN_STATUS_IO_INVALID_COMPRESSED_BUFFER_SIZE); + } + + pOutputEnd = pOutput + *pnOutputSize; + + XN_CHECK_OUTPUT_OVERFLOW(pOutput + (nInputSize * 2), pOutputEnd); + + while (pInput != pInputEnd) + { + nValue1 = pInput[0]; + nValue2 = pInput[1]; + + pOutput[0] = nValue1 >> 4; + pOutput[1] = nValue1 & 0xF; + pOutput[2] = nValue2 >> 4; + pOutput[3] = nValue2 & 0xF; + + pOutput+=4; + pInput+=2; + } + + *pnOutputSize = (pOutput - pOrigOutput); + + // All is good... + return (XN_STATUS_OK); +} + +void XnStreamJPEGCompDummyFunction(struct jpeg_compress_struct* pjCompStruct) +{ + // Dummy libjpeg function to wrap internal buffers usage... +} + +boolean XnStreamJPEGCompDummyFailFunction(struct jpeg_compress_struct* pjCompStruct) +{ + // If we ever got to the point we need to allocate more memory, something is wrong! + return (FALSE); +} + +XN_FORMATS_API XnStatus XnStreamInitCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_OUTPUT_PTR(pStreamCompJPEGContext); + + pStreamCompJPEGContext->jCompStruct.err = jpeg_std_error(&pStreamCompJPEGContext->jErrMgr); + + jpeg_create_compress(&pStreamCompJPEGContext->jCompStruct); + + pStreamCompJPEGContext->jCompStruct.dest = &pStreamCompJPEGContext->jDestMgr; + pStreamCompJPEGContext->jCompStruct.dest->init_destination = XnStreamJPEGCompDummyFunction; + pStreamCompJPEGContext->jCompStruct.dest->empty_output_buffer = XnStreamJPEGCompDummyFailFunction; + pStreamCompJPEGContext->jCompStruct.dest->term_destination = XnStreamJPEGCompDummyFunction; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamFreeCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); + + jpeg_destroy_compress(&pStreamCompJPEGContext->jCompStruct); + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamCompressImage8J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality) +{ + // Local function variables + XnUInt8* pCurrScanline = (XnUInt8*)pInput; + XnUInt32 nYIndex = 0; + jpeg_compress_struct* pjCompStruct = NULL; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_OUTPUT_PTR(pOutput); + XN_VALIDATE_OUTPUT_PTR(pnOutputSize); + + pjCompStruct = &pStreamCompJPEGContext->jCompStruct; + + pjCompStruct->in_color_space = JCS_GRAYSCALE; + jpeg_set_defaults(pjCompStruct); + pjCompStruct->input_components = 1; + pjCompStruct->num_components = 1; + pjCompStruct->image_width = nXRes; + pjCompStruct->image_height = nYRes; + pjCompStruct->data_precision = 8; + pjCompStruct->input_gamma = 1.0; + + jpeg_set_quality(pjCompStruct, nQuality, FALSE); + + pjCompStruct->dest->next_output_byte = (JOCTET*)pOutput; + pjCompStruct->dest->free_in_buffer = *pnOutputSize; + + jpeg_start_compress(pjCompStruct, TRUE); + + for (nYIndex = 0; nYIndex < nYRes; nYIndex++) + { + jpeg_write_scanlines(pjCompStruct, &pCurrScanline, 1); + + pCurrScanline += nXRes; + } + + jpeg_finish_compress(pjCompStruct); + + *pnOutputSize -= pjCompStruct->dest->free_in_buffer; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamCompressImage24J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality) +{ + // Local function variables + XnUInt8* pCurrScanline = (XnUChar*)pInput; + XnUInt32 nYIndex = 0; + XnUInt32 nScanLineSize = 0; + jpeg_compress_struct* pjCompStruct = NULL; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pStreamCompJPEGContext); + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_OUTPUT_PTR(pOutput); + XN_VALIDATE_OUTPUT_PTR(pnOutputSize); + + pjCompStruct = &pStreamCompJPEGContext->jCompStruct; + + pjCompStruct->in_color_space = JCS_RGB; + jpeg_set_defaults(pjCompStruct); + pjCompStruct->input_components = 3; + pjCompStruct->num_components = 3; + pjCompStruct->image_width = nXRes; + pjCompStruct->image_height = nYRes; + pjCompStruct->data_precision = 8; + pjCompStruct->input_gamma = 1.0; + + jpeg_set_quality(pjCompStruct, nQuality, FALSE); + + pjCompStruct->dest->next_output_byte = (JOCTET*)pOutput; + pjCompStruct->dest->free_in_buffer = *pnOutputSize; + + jpeg_start_compress(pjCompStruct, TRUE); + + nScanLineSize = nXRes * 3; + for (nYIndex = 0; nYIndex < nYRes; nYIndex++) + { + jpeg_write_scanlines(pjCompStruct, &pCurrScanline, 1); + + pCurrScanline += nScanLineSize; + } + + jpeg_finish_compress(pjCompStruct); + + *pnOutputSize -= pjCompStruct->dest->free_in_buffer; + + // All is good... + return (XN_STATUS_OK); +} + +void XnStreamJPEGDecompDummyFunction(struct jpeg_decompress_struct* pjDecompStruct) +{ + // Dummy libjpeg function to wrap internal buffers usage... +} + +boolean XnStreamJPEGDecompDummyFailFunction(struct jpeg_decompress_struct* pjDecompStruct) +{ + // If we ever got to the point we need to allocate more memory, something is wrong! + return (FALSE); +} + +void XnStreamJPEGDecompSkipFunction(struct jpeg_decompress_struct* pjDecompStruct, long nNumBytes) +{ + // Skip bytes in the internal buffer + pjDecompStruct->src->next_input_byte += (size_t)nNumBytes; + pjDecompStruct->src->bytes_in_buffer -= (size_t)nNumBytes; +} + +void XnStreamJPEGDummyErrorExit(j_common_ptr cinfo) +{ + XnLibJpegErrorMgr* errMgr = (XnLibJpegErrorMgr*)cinfo->err; + + longjmp(errMgr->setjmpBuffer, 1); +} + +void XnStreamJPEGOutputMessage(j_common_ptr cinfo) +{ + struct jpeg_error_mgr* err = cinfo->err; + int msg_code = err->msg_code; + if (msg_code == JWRN_EXTRANEOUS_DATA) + { + // NOTE: we are aware this problem occurs. Log a warning every once in a while + static XnUInt32 nTimes = 0; + if (++nTimes == 50) + { + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + //Temporary disabled this error since it happens all the time and it's a known issue. + //xnLogWarning(XN_MASK_JPEG, "JPEG: The following warning occurred 50 times: %s", buffer); + nTimes = 0; + } + } + else + { + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + xnLogWarning(XN_MASK_JPEG, "JPEG: %s", buffer); + } +} + +XN_FORMATS_API XnStatus XnStreamInitUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_OUTPUT_PTR(pStreamUncompJPEGContext); + + pStreamUncompJPEGContext->jDecompStruct.err = jpeg_std_error(&pStreamUncompJPEGContext->jErrMgr.pub); + pStreamUncompJPEGContext->jErrMgr.pub.output_message = XnStreamJPEGOutputMessage; + pStreamUncompJPEGContext->jErrMgr.pub.error_exit = XnStreamJPEGDummyErrorExit; + + jpeg_create_decompress(&pStreamUncompJPEGContext->jDecompStruct); + + pStreamUncompJPEGContext->jDecompStruct.src = &pStreamUncompJPEGContext->jSrcMgr; + pStreamUncompJPEGContext->jDecompStruct.src->init_source = XnStreamJPEGDecompDummyFunction; + pStreamUncompJPEGContext->jDecompStruct.src->fill_input_buffer = XnStreamJPEGDecompDummyFailFunction; + pStreamUncompJPEGContext->jDecompStruct.src->skip_input_data = XnStreamJPEGDecompSkipFunction; + pStreamUncompJPEGContext->jDecompStruct.src->resync_to_restart = jpeg_resync_to_restart; + pStreamUncompJPEGContext->jDecompStruct.src->term_source = XnStreamJPEGDecompDummyFunction; + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamFreeUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext) +{ + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pStreamUncompJPEGContext); + + jpeg_destroy_decompress(&pStreamUncompJPEGContext->jDecompStruct); + + // All is good... + return (XN_STATUS_OK); +} + +XN_FORMATS_API XnStatus XnStreamUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext, const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize) +{ + // Local function variables + XnUInt8* pCurrScanline = pOutput; + XnUInt8* pNextScanline = NULL; + XnUInt8* pOutputEnd = 0; + XnUInt32 nScanLineSize = 0; + XnUInt32 nOutputSize = 0; + jpeg_decompress_struct* pjDecompStruct = NULL; + + // Validate the input/output pointers (to make sure none of them is NULL) + XN_VALIDATE_INPUT_PTR(pStreamUncompJPEGContext); + XN_VALIDATE_INPUT_PTR(pInput); + XN_VALIDATE_OUTPUT_PTR(pOutput); + XN_VALIDATE_OUTPUT_PTR(pnOutputSize); + + if (nInputSize == 0) + { + return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL); + } + + pOutputEnd = pOutput + *pnOutputSize; + + pjDecompStruct = &pStreamUncompJPEGContext->jDecompStruct; + + pjDecompStruct->src->bytes_in_buffer = nInputSize; + pjDecompStruct->src->next_input_byte = pInput; + + if (setjmp(pStreamUncompJPEGContext->jErrMgr.setjmpBuffer)) + { + //If we get here, the JPEG code has signaled an error. + XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); + XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); + + *pnOutputSize = 0; + + return (XN_STATUS_IO_DECOMPRESSION_FAILED); + } + + jpeg_read_header(pjDecompStruct, TRUE); + + jpeg_start_decompress(pjDecompStruct); + + nScanLineSize = pjDecompStruct->output_width * pjDecompStruct->num_components; + + nOutputSize = pjDecompStruct->output_height * nScanLineSize; + if (nOutputSize > *pnOutputSize) + { + XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); + XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); + + *pnOutputSize = 0; + + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + while (pStreamUncompJPEGContext->jDecompStruct.output_scanline < pStreamUncompJPEGContext->jDecompStruct.output_height) + { + pNextScanline = pCurrScanline+nScanLineSize; + + if (pNextScanline > pOutputEnd) + { + XnStreamFreeUncompressImageJ(pStreamUncompJPEGContext); + XnStreamInitUncompressImageJ(pStreamUncompJPEGContext); + + *pnOutputSize = 0; + + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + jpeg_read_scanlines(pjDecompStruct, &pCurrScanline, 1); + pCurrScanline = pNextScanline; + } + + jpeg_finish_decompress(pjDecompStruct); + + *pnOutputSize = nOutputSize; + + // All is good... + return (XN_STATUS_OK); +} diff --git a/Source/XnFormats/XnStreamCompression.h b/Source/XnFormats/XnStreamCompression.h index 35f31d1..4d7c5a8 100644 --- a/Source/XnFormats/XnStreamCompression.h +++ b/Source/XnFormats/XnStreamCompression.h @@ -1,104 +1,104 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - - -#ifndef _XN_STREAMCOMPRESSION_H_ -#define _XN_STREAMCOMPRESSION_H_ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnFormats.h" -#include -#include -#include - -//--------------------------------------------------------------------------- -// Defines -//--------------------------------------------------------------------------- -#define XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO 1.333F -#define XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO 1.333F -#define XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO 1.2F -#define XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO 0.51F -#define XN_STREAM_COMPRESSION_JPEG_DEFAULT_QUALITY 90 - -#define XN_STREAM_STRING_BAD_FORMAT -1 - -#define XN_MASK_JPEG "JPEG" - -//--------------------------------------------------------------------------- -// Structs -//--------------------------------------------------------------------------- -typedef struct XnLibJpegErrorMgr -{ - struct jpeg_error_mgr pub; - - jmp_buf setjmpBuffer; -} XnLibJpegErrorMgr; - -typedef struct XnStreamCompJPEGContext -{ - jpeg_compress_struct jCompStruct; - jpeg_error_mgr jErrMgr; - struct jpeg_destination_mgr jDestMgr; -} XnStreamCompJPEGContext; - -typedef struct XnStreamUncompJPEGContext -{ - jpeg_decompress_struct jDecompStruct; - XnLibJpegErrorMgr jErrMgr; - struct jpeg_source_mgr jSrcMgr; -} XnStreamUncompJPEGContext; - -//--------------------------------------------------------------------------- -// Functions Declaration -//--------------------------------------------------------------------------- -XN_FORMATS_API XnStatus XnStreamCompressDepth16Z(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); -XN_FORMATS_API XnStatus XnStreamCompressDepth16ZWithEmbTable(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nMaxValue); -XN_FORMATS_API XnStatus XnStreamUncompressDepth16Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize); -XN_FORMATS_API XnStatus XnStreamUncompressDepth16ZWithEmbTable(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize); - -XN_FORMATS_API XnStatus XnStreamCompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); -XN_FORMATS_API XnStatus XnStreamUncompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); - -XN_FORMATS_API XnStatus XnStreamCompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); -XN_FORMATS_API XnStatus XnStreamUncompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); - -void XnStreamJPEGCompDummyFunction(struct jpeg_compress_struct* pjCompStruct); -boolean XnStreamJPEGCompDummyFailFunction(struct jpeg_compress_struct* pjCompStruct); -XN_FORMATS_API XnStatus XnStreamInitCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext); -XN_FORMATS_API XnStatus XnStreamFreeCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext); -XN_FORMATS_API XnStatus XnStreamCompressImage8J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality); -XN_FORMATS_API XnStatus XnStreamCompressImage24J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality); - -void XnStreamJPEGDecompDummyFunction(struct jpeg_decompress_struct* pjDecompStruct); -boolean XnStreamJPEGDecompDummyFailFunction(struct jpeg_decompress_struct* pjDecompStruct); -void XnStreamJPEGDecompSkipFunction(struct jpeg_decompress_struct* pjDecompStruct, XnInt nNumBytes); -XN_FORMATS_API XnStatus XnStreamInitUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext); -XN_FORMATS_API XnStatus XnStreamFreeUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext); -XN_FORMATS_API XnStatus XnStreamUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext, const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); - -#endif //_XN_STREAMCOMPRESSION_H_ +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + + +#ifndef _XN_STREAMCOMPRESSION_H_ +#define _XN_STREAMCOMPRESSION_H_ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnFormats.h" +#include +#include +#include + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- +#define XN_STREAM_COMPRESSION_DEPTH16Z_WORSE_RATIO 1.333F +#define XN_STREAM_COMPRESSION_IMAGE8Z_WORSE_RATIO 1.333F +#define XN_STREAM_COMPRESSION_IMAGEJ_WORSE_RATIO 1.2F +#define XN_STREAM_COMPRESSION_CONF4_WORSE_RATIO 0.51F +#define XN_STREAM_COMPRESSION_JPEG_DEFAULT_QUALITY 90 + +#define XN_STREAM_STRING_BAD_FORMAT -1 + +#define XN_MASK_JPEG "JPEG" + +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- +typedef struct XnLibJpegErrorMgr +{ + struct jpeg_error_mgr pub; + + jmp_buf setjmpBuffer; +} XnLibJpegErrorMgr; + +typedef struct XnStreamCompJPEGContext +{ + jpeg_compress_struct jCompStruct; + jpeg_error_mgr jErrMgr; + struct jpeg_destination_mgr jDestMgr; +} XnStreamCompJPEGContext; + +typedef struct XnStreamUncompJPEGContext +{ + jpeg_decompress_struct jDecompStruct; + XnLibJpegErrorMgr jErrMgr; + struct jpeg_source_mgr jSrcMgr; +} XnStreamUncompJPEGContext; + +//--------------------------------------------------------------------------- +// Functions Declaration +//--------------------------------------------------------------------------- +XN_FORMATS_API XnStatus XnStreamCompressDepth16Z(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); +XN_FORMATS_API XnStatus XnStreamCompressDepth16ZWithEmbTable(const XnUInt16* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nMaxValue); +XN_FORMATS_API XnStatus XnStreamUncompressDepth16Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize); +XN_FORMATS_API XnStatus XnStreamUncompressDepth16ZWithEmbTable(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt16* pOutput, XnUInt32* pnOutputSize); + +XN_FORMATS_API XnStatus XnStreamCompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); +XN_FORMATS_API XnStatus XnStreamUncompressImage8Z(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); + +XN_FORMATS_API XnStatus XnStreamCompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); +XN_FORMATS_API XnStatus XnStreamUncompressConf4(const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); + +void XnStreamJPEGCompDummyFunction(struct jpeg_compress_struct* pjCompStruct); +boolean XnStreamJPEGCompDummyFailFunction(struct jpeg_compress_struct* pjCompStruct); +XN_FORMATS_API XnStatus XnStreamInitCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext); +XN_FORMATS_API XnStatus XnStreamFreeCompressImageJ(XnStreamCompJPEGContext* pStreamCompJPEGContext); +XN_FORMATS_API XnStatus XnStreamCompressImage8J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality); +XN_FORMATS_API XnStatus XnStreamCompressImage24J(XnStreamCompJPEGContext* pStreamCompJPEGContext, const XnUInt8* pInput, XnUInt8* pOutput, XnUInt32* pnOutputSize, const XnUInt32 nXRes, const XnUInt32 nYRes, const XnUInt32 nQuality); + +void XnStreamJPEGDecompDummyFunction(struct jpeg_decompress_struct* pjDecompStruct); +boolean XnStreamJPEGDecompDummyFailFunction(struct jpeg_decompress_struct* pjDecompStruct); +void XnStreamJPEGDecompSkipFunction(struct jpeg_decompress_struct* pjDecompStruct, XnInt nNumBytes); +XN_FORMATS_API XnStatus XnStreamInitUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext); +XN_FORMATS_API XnStatus XnStreamFreeUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext); +XN_FORMATS_API XnStatus XnStreamUncompressImageJ(XnStreamUncompJPEGContext* pStreamUncompJPEGContext, const XnUInt8* pInput, const XnUInt32 nInputSize, XnUInt8* pOutput, XnUInt32* pnOutputSize); + +#endif //_XN_STREAMCOMPRESSION_H_ diff --git a/Source/XnFormats/XnUncompressedCodec.h b/Source/XnFormats/XnUncompressedCodec.h index cd6e2e5..8fddfc7 100644 --- a/Source/XnFormats/XnUncompressedCodec.h +++ b/Source/XnFormats/XnUncompressedCodec.h @@ -1,74 +1,74 @@ -/***************************************************************************** -* * -* PrimeSense Sensor 5.0 Alpha * -* Copyright (C) 2010 PrimeSense Ltd. * -* * -* This file is part of PrimeSense Common. * -* * -* PrimeSense Sensor is free software: you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License as published * -* by the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* PrimeSense Sensor is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with PrimeSense Sensor. If not, see . * -* * -*****************************************************************************/ - - - - - -#ifndef __XN_UNCOMPRESSED_CODEC_H__ -#define __XN_UNCOMPRESSED_CODEC_H__ - -//--------------------------------------------------------------------------- -// Includes -//--------------------------------------------------------------------------- -#include "XnCodecBase.h" - -//--------------------------------------------------------------------------- -// Types -//--------------------------------------------------------------------------- -class XN_FORMATS_CPP_API XnUncompressedCodec : public XnCodecBase -{ -public: - XnUncompressedCodec() {} - virtual ~XnUncompressedCodec() {} - - virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_NONE; } - virtual XnFloat GetWorseCompressionRatio() const { return 1.0; } - virtual XnUInt32 GetOverheadSize() const { return 0; } - -protected: - virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) - { - if (nDataSize > *pnCompressedDataSize) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - xnOSMemCopy(pCompressedData, pData, nDataSize); - *pnCompressedDataSize = nDataSize; - return (XN_STATUS_OK); - } - - virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) - { - if (nCompressedDataSize > *pnDataSize) - { - return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); - } - - xnOSMemCopy(pData, pCompressedData, nCompressedDataSize); - *pnDataSize = nCompressedDataSize; - return (XN_STATUS_OK); - } -}; - +/***************************************************************************** +* * +* PrimeSense Sensor 5.0 Alpha * +* Copyright (C) 2010 PrimeSense Ltd. * +* * +* This file is part of PrimeSense Common. * +* * +* PrimeSense Sensor is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 of the License, or * +* (at your option) any later version. * +* * +* PrimeSense Sensor is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with PrimeSense Sensor. If not, see . * +* * +*****************************************************************************/ + + + + + +#ifndef __XN_UNCOMPRESSED_CODEC_H__ +#define __XN_UNCOMPRESSED_CODEC_H__ + +//--------------------------------------------------------------------------- +// Includes +//--------------------------------------------------------------------------- +#include "XnCodecBase.h" + +//--------------------------------------------------------------------------- +// Types +//--------------------------------------------------------------------------- +class XN_FORMATS_CPP_API XnUncompressedCodec : public XnCodecBase +{ +public: + XnUncompressedCodec() {} + virtual ~XnUncompressedCodec() {} + + virtual XnCompressionFormats GetCompressionFormat() const { return XN_COMPRESSION_NONE; } + virtual XnFloat GetWorseCompressionRatio() const { return 1.0; } + virtual XnUInt32 GetOverheadSize() const { return 0; } + +protected: + virtual XnStatus CompressImpl(const XnUChar* pData, XnUInt32 nDataSize, XnUChar* pCompressedData, XnUInt32* pnCompressedDataSize) + { + if (nDataSize > *pnCompressedDataSize) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + xnOSMemCopy(pCompressedData, pData, nDataSize); + *pnCompressedDataSize = nDataSize; + return (XN_STATUS_OK); + } + + virtual XnStatus DecompressImpl(const XnUChar* pCompressedData, XnUInt32 nCompressedDataSize, XnUChar* pData, XnUInt32* pnDataSize) + { + if (nCompressedDataSize > *pnDataSize) + { + return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); + } + + xnOSMemCopy(pData, pCompressedData, nCompressedDataSize); + *pnDataSize = nCompressedDataSize; + return (XN_STATUS_OK); + } +}; + #endif //__XN_UNCOMPRESSED_CODEC_H__ \ No newline at end of file