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