Skip to content

Commit 834ad74

Browse files
committed
New VideoToolbox rgb packet processor
Mac OS X >= 10.8 has hardware accelerated jpeg decoding (a bit hidden)
1 parent 9f19d7a commit 834ad74

File tree

6 files changed

+268
-13
lines changed

6 files changed

+268
-13
lines changed

CMakeLists.txt

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
7676
# dependencies
7777
FIND_PACKAGE(PkgConfig) # try find PKGConfig as it will be used if found
7878
FIND_PACKAGE(LibUSB REQUIRED)
79-
FIND_PACKAGE(TurboJPEG REQUIRED) #does not provide a package-config file
8079

8180
# Add includes
8281
INCLUDE_DIRECTORIES(
@@ -85,7 +84,6 @@ INCLUDE_DIRECTORIES(
8584
${PROJECT_BINARY_DIR} # for generated headers
8685
${LIBFREENECT2_THREADING_INCLUDE_DIR}
8786
${LibUSB_INCLUDE_DIRS}
88-
${TurboJPEG_INCLUDE_DIRS}
8987
)
9088

9189
SET(RESOURCES_INC_FILE "${PROJECT_BINARY_DIR}/resources.inc.h")
@@ -125,7 +123,6 @@ SET(SOURCES
125123
src/packet_pipeline.cpp
126124
src/rgb_packet_stream_parser.cpp
127125
src/rgb_packet_processor.cpp
128-
src/turbo_jpeg_rgb_packet_processor.cpp
129126
src/depth_packet_stream_parser.cpp
130127
src/depth_packet_processor.cpp
131128
src/cpu_depth_packet_processor.cpp
@@ -143,15 +140,61 @@ SET(SOURCES
143140

144141
SET(LIBRARIES
145142
${LibUSB_LIBRARIES}
146-
${TurboJPEG_LIBRARIES}
147143
${LIBFREENECT2_THREADING_LIBRARIES}
148144
)
149145

150146
SET(LIBFREENECT2_DLLS
151147
${LibUSB_DLL}
152-
${TurboJPEG_DLL}
153148
)
154149

150+
IF(APPLE)
151+
FIND_LIBRARY(VIDEOTOOLBOX_LIBRARY VideoToolbox)
152+
153+
IF(VIDEOTOOLBOX_LIBRARY)
154+
SET(LIBFREENECT2_WITH_VT_SUPPORT 1)
155+
156+
FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED)
157+
FIND_LIBRARY(COREMEDIA_LIBRARY CoreMedia REQUIRED)
158+
FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo REQUIRED)
159+
160+
LIST(APPEND SOURCES
161+
src/vt_rgb_packet_processor.cpp
162+
)
163+
164+
LIST(APPEND LIBRARIES
165+
${VIDEOTOOLBOX_LIBRARY}
166+
${COREFOUNDATION_LIBRARY}
167+
${COREMEDIA_LIBRARY}
168+
${COREVIDEO_LIBRARY}
169+
)
170+
ENDIF(VIDEOTOOLBOX_LIBRARY)
171+
ENDIF(APPLE)
172+
173+
IF(LIBFREENECT2_WITH_VT_SUPPORT)
174+
FIND_PACKAGE(TurboJPEG)
175+
ELSE()
176+
FIND_PACKAGE(TurboJPEG REQUIRED)
177+
ENDIF()
178+
179+
IF(TurboJPEG_FOUND)
180+
SET(LIBFREENECT2_WITH_TURBOJPEG_SUPPORT 1)
181+
182+
INCLUDE_DIRECTORIES(${TurboJPEG_INCLUDE_DIRS})
183+
184+
LIST(APPEND SOURCES
185+
src/turbo_jpeg_rgb_packet_processor.cpp
186+
)
187+
188+
LIST(APPEND LIBRARIES
189+
${TurboJPEG_LIBRARIES}
190+
)
191+
192+
LIST(APPEND LIBFREENECT2_DLLS
193+
${TurboJPEG_DLL}
194+
)
195+
196+
ENDIF()
197+
155198
IF(ENABLE_OPENGL)
156199
FIND_PACKAGE(GLFW3)
157200
FIND_PACKAGE(OpenGL)

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,12 @@ Use your favorite package managers (brew, ports, etc.) to install most if not al
189189

190190
1. ``cd`` into a directory where you want to keep libfreenect2 stuff in
191191
1. Make sure these build tools are available: wget, git, cmake, pkg-config. Xcode may provide some of them. Install the rest via package managers.
192-
1. Install dependencies: libusb, TurboJPEG, GLFW, OpenNI2 (optional).
192+
1. Install dependencies: libusb, TurboJPEG (optional), GLFW, OpenNI2 (optional).
193193

194194
```
195195
brew update
196196
brew install libusb
197197
brew tap homebrew/science
198-
brew install jpeg-turbo
199198
brew tap homebrew/versions
200199
brew install glfw3
201200
brew install openni2
@@ -205,6 +204,8 @@ export OPENNI2_INCLUDE=/usr/local/include/ni2
205204

206205
It **is** now recommended to install libusb from package managers instead of building from source locally. Previously it was not recommended but that is no longer the case.
207206

207+
You are still able to build with optional TurboJPEG support with ```brew install jpeg-turbo``` along with other dependencies
208+
208209
It is not recommended to build TurboJPEG from source, which may produce corrupted results on Mac OSX according to user reports. Install TurboJPEG binary only from package managers.
209210

210211
1. Download the libfreenect2 repository

include/internal/libfreenect2/rgb_packet_processor.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class DumpRgbPacketProcessor : public RgbPacketProcessor
7777
virtual void process(const libfreenect2::RgbPacket &packet);
7878
};
7979

80+
#ifdef LIBFREENECT2_WITH_TURBOJPEG_SUPPORT
8081
class TurboJpegRgbPacketProcessorImpl;
8182

8283
/** Processor to decode JPEG to image, using TurboJpeg. */
@@ -90,6 +91,22 @@ class TurboJpegRgbPacketProcessor : public RgbPacketProcessor
9091
private:
9192
TurboJpegRgbPacketProcessorImpl *impl_; ///< Decoder implementation.
9293
};
94+
#endif
95+
96+
#ifdef LIBFREENECT2_WITH_VT_SUPPORT
97+
class VTRgbPacketProcessorImpl;
98+
99+
class LIBFREENECT2_API VTRgbPacketProcessor : public RgbPacketProcessor
100+
{
101+
public:
102+
VTRgbPacketProcessor();
103+
virtual ~VTRgbPacketProcessor();
104+
protected:
105+
virtual void process(const libfreenect2::RgbPacket &packet);
106+
private:
107+
VTRgbPacketProcessorImpl *impl_;
108+
};
109+
#endif
93110

94111
} /* namespace libfreenect2 */
95112
#endif /* RGB_PACKET_PROCESSOR_H_ */

include/libfreenect2/config.h.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#cmakedefine LIBFREENECT2_WITH_OPENCL_SUPPORT
4545
#cmakedefine LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD
4646

47+
#cmakedefine LIBFREENECT2_WITH_VT_SUPPORT
48+
49+
#cmakedefine LIBFREENECT2_WITH_TURBOJPEG_SUPPORT
50+
4751
#cmakedefine LIBFREENECT2_THREADING_STDLIB
4852

4953
#cmakedefine LIBFREENECT2_THREADING_TINYTHREAD

src/packet_pipeline.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@
3636
namespace libfreenect2
3737
{
3838

39+
static RgbPacketProcessor *getDefaultRgbPacketProcessor()
40+
{
41+
#ifdef LIBFREENECT2_WITH_VT_SUPPORT
42+
return new VTRgbPacketProcessor();
43+
#endif
44+
#ifdef LIBFREENECT2_WITH_TURBOJPEG_SUPPORT
45+
return new TurboJpegRgbPacketProcessor();
46+
#endif
47+
return NULL;
48+
}
49+
3950
class PacketPipelineComponents
4051
{
4152
public:
@@ -104,16 +115,16 @@ DepthPacketProcessor *PacketPipeline::getDepthPacketProcessor() const
104115
}
105116

106117
CpuPacketPipeline::CpuPacketPipeline()
107-
{
108-
comp_->initialize(new TurboJpegRgbPacketProcessor(), new CpuDepthPacketProcessor());
118+
{
119+
comp_->initialize(getDefaultRgbPacketProcessor(), new CpuDepthPacketProcessor());
109120
}
110121

111122
CpuPacketPipeline::~CpuPacketPipeline() { }
112123

113124
#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT
114125
OpenGLPacketPipeline::OpenGLPacketPipeline(void *parent_opengl_context, bool debug) : parent_opengl_context_(parent_opengl_context), debug_(debug)
115-
{
116-
comp_->initialize(new TurboJpegRgbPacketProcessor(), new OpenGLDepthPacketProcessor(parent_opengl_context_, debug_));
126+
{
127+
comp_->initialize(getDefaultRgbPacketProcessor(), new OpenGLDepthPacketProcessor(parent_opengl_context_, debug_));
117128
}
118129

119130
OpenGLPacketPipeline::~OpenGLPacketPipeline() { }
@@ -123,8 +134,8 @@ OpenGLPacketPipeline::~OpenGLPacketPipeline() { }
123134
#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT
124135

125136
OpenCLPacketPipeline::OpenCLPacketPipeline(const int deviceId) : deviceId(deviceId)
126-
{
127-
comp_->initialize(new TurboJpegRgbPacketProcessor(), new OpenCLDepthPacketProcessor(deviceId));
137+
{
138+
comp_->initialize(getDefaultRgbPacketProcessor(), new OpenCLDepthPacketProcessor(deviceId));
128139
}
129140

130141
OpenCLPacketPipeline::~OpenCLPacketPipeline() { }

src/vt_rgb_packet_processor.cpp

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* This file is part of the OpenKinect Project. http://www.openkinect.org
3+
*
4+
* Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file
5+
* for details.
6+
*
7+
* This code is licensed to you under the terms of the Apache License, version
8+
* 2.0, or, at your option, the terms of the GNU General Public License,
9+
* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10+
* or the following URLs:
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* http://www.gnu.org/licenses/gpl-2.0.txt
13+
*
14+
* If you redistribute this file in source form, modified or unmodified, you
15+
* may:
16+
* 1) Leave this header intact and distribute it under the same terms,
17+
* accompanying it with the APACHE20 and GPL20 files, or
18+
* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19+
* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20+
* In all cases you must keep the copyright notice intact and include a copy
21+
* of the CONTRIB file.
22+
*
23+
* Binary distributions must follow the binary distribution requirements of
24+
* either License.
25+
*/
26+
27+
28+
#include <libfreenect2/rgb_packet_processor.h>
29+
#include <libfreenect2/logging.h>
30+
31+
#include <VideoToolbox/VideoToolbox.h>
32+
33+
namespace libfreenect2 {
34+
35+
class VTFrame: public Frame
36+
{
37+
public:
38+
VTFrame(size_t width, size_t height, size_t bytes_per_pixel, CVPixelBufferRef pixelBuffer) :
39+
Frame(width,
40+
height,
41+
bytes_per_pixel,
42+
reinterpret_cast<unsigned char *>(CVPixelBufferGetBaseAddress(lockPixelBuffer(pixelBuffer)))),
43+
pixelBuffer(pixelBuffer) {
44+
}
45+
46+
~VTFrame() {
47+
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
48+
CVPixelBufferRelease(pixelBuffer);
49+
}
50+
51+
protected:
52+
CVPixelBufferRef lockPixelBuffer(CVPixelBufferRef _pixelBuffer) {
53+
CVPixelBufferLockBaseAddress(_pixelBuffer, 0);
54+
55+
return _pixelBuffer;
56+
}
57+
58+
CVPixelBufferRef pixelBuffer;
59+
};
60+
61+
class VTRgbPacketProcessorImpl: public WithPerfLogging
62+
{
63+
public:
64+
CMFormatDescriptionRef format;
65+
VTDecompressionSessionRef decoder;
66+
67+
VTRgbPacketProcessorImpl() {
68+
int32_t width = 1920, height = 1080;
69+
70+
CMVideoFormatDescriptionCreate(NULL, kCMVideoCodecType_JPEG, width, height, nil, &format);
71+
72+
const void *decoderSpecificationKeys[] = {kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder};
73+
const void *decoderSpecificationValues[] = {kCFBooleanTrue};
74+
CFDictionaryRef decoderSpecification = CFDictionaryCreate(NULL,
75+
decoderSpecificationKeys,
76+
decoderSpecificationValues,
77+
1,
78+
&kCFTypeDictionaryKeyCallBacks,
79+
&kCFTypeDictionaryValueCallBacks);
80+
81+
int32_t pixelFormat = kCVPixelFormatType_32BGRA;
82+
const void *outputKeys[] = {kCVPixelBufferPixelFormatTypeKey, kCVPixelBufferWidthKey, kCVPixelBufferHeightKey};
83+
const void *outputValues[] =
84+
{CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormat), CFNumberCreate(NULL, kCFNumberSInt32Type, &width),
85+
CFNumberCreate(NULL, kCFNumberSInt32Type, &height)};
86+
87+
CFDictionaryRef outputConfiguration = CFDictionaryCreate(NULL,
88+
outputKeys,
89+
outputValues,
90+
3,
91+
&kCFTypeDictionaryKeyCallBacks,
92+
&kCFTypeDictionaryValueCallBacks);
93+
94+
VTDecompressionOutputCallbackRecord callback = {&VTRgbPacketProcessorImpl::decodeFrame, NULL};
95+
96+
VTDecompressionSessionCreate(NULL, format, decoderSpecification, outputConfiguration, &callback, &decoder);
97+
98+
CFRelease(decoderSpecification);
99+
CFRelease(outputConfiguration);
100+
}
101+
102+
~VTRgbPacketProcessorImpl() {
103+
VTDecompressionSessionInvalidate(decoder);
104+
CFRelease(decoder);
105+
CFRelease(format);
106+
}
107+
108+
static void decodeFrame(void *decompressionOutputRefCon,
109+
void *sourceFrameRefCon,
110+
OSStatus status,
111+
VTDecodeInfoFlags infoFlags,
112+
CVImageBufferRef pixelBuffer,
113+
CMTime presentationTimeStamp,
114+
CMTime presentationDuration) {
115+
CVPixelBufferRef *outputPixelBuffer = (CVPixelBufferRef *) sourceFrameRefCon;
116+
*outputPixelBuffer = CVPixelBufferRetain(pixelBuffer);
117+
}
118+
};
119+
120+
VTRgbPacketProcessor::VTRgbPacketProcessor()
121+
: RgbPacketProcessor ()
122+
, impl_(new VTRgbPacketProcessorImpl())
123+
{
124+
}
125+
126+
VTRgbPacketProcessor::~VTRgbPacketProcessor()
127+
{
128+
delete impl_;
129+
}
130+
131+
void VTRgbPacketProcessor::process(const RgbPacket &packet)
132+
{
133+
if (listener_ != 0) {
134+
impl_->startTiming();
135+
136+
CMBlockBufferRef blockBuffer;
137+
CMBlockBufferCreateWithMemoryBlock(
138+
NULL,
139+
packet.jpeg_buffer,
140+
packet.jpeg_buffer_length,
141+
kCFAllocatorNull,
142+
NULL,
143+
0,
144+
packet.jpeg_buffer_length,
145+
0,
146+
&blockBuffer
147+
);
148+
149+
CMSampleBufferRef sampleBuffer;
150+
CMSampleBufferCreateReady(
151+
NULL,
152+
blockBuffer,
153+
impl_->format,
154+
1,
155+
0,
156+
NULL,
157+
0,
158+
NULL,
159+
&sampleBuffer
160+
);
161+
162+
CVPixelBufferRef pixelBuffer = NULL;
163+
VTDecompressionSessionDecodeFrame(impl_->decoder, sampleBuffer, 0, &pixelBuffer, NULL);
164+
165+
Frame *frame = new VTFrame(1920, 1080, 4, pixelBuffer);
166+
167+
frame->timestamp = packet.timestamp;
168+
frame->sequence = packet.sequence;
169+
170+
listener_->onNewFrame(Frame::Color, frame);
171+
172+
CFRelease(sampleBuffer);
173+
CFRelease(blockBuffer);
174+
175+
impl_->stopTiming(LOG_INFO);
176+
}
177+
}
178+
179+
} /* namespace libfreenect2 */

0 commit comments

Comments
 (0)