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
+
30
+ #include < VideoToolbox/VideoToolbox.h>
31
+ #include < iostream>
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
62
+ {
63
+ public:
64
+ CMFormatDescriptionRef format;
65
+ VTDecompressionSessionRef decoder;
66
+
67
+ double timing_acc;
68
+ double timing_acc_n;
69
+
70
+ Timer timer;
71
+
72
+ VTRgbPacketProcessorImpl () {
73
+ timing_acc = 0.0 ;
74
+ timing_acc_n = 0.0 ;
75
+
76
+ int32_t width = 1920 , height = 1080 ;
77
+
78
+ CMVideoFormatDescriptionCreate (NULL , kCMVideoCodecType_JPEG , width, height, nil, &format);
79
+
80
+ const void *decoderSpecificationKeys[] = {kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder };
81
+ const void *decoderSpecificationValues[] = {kCFBooleanTrue };
82
+ CFDictionaryRef decoderSpecification = CFDictionaryCreate (NULL ,
83
+ decoderSpecificationKeys,
84
+ decoderSpecificationValues,
85
+ 1 ,
86
+ &kCFTypeDictionaryKeyCallBacks ,
87
+ &kCFTypeDictionaryValueCallBacks );
88
+
89
+ int32_t pixelFormat = kCVPixelFormatType_32BGRA ;
90
+ const void *outputKeys[] = {kCVPixelBufferPixelFormatTypeKey , kCVPixelBufferWidthKey , kCVPixelBufferHeightKey };
91
+ const void *outputValues[] =
92
+ {CFNumberCreate (NULL , kCFNumberSInt32Type , &pixelFormat), CFNumberCreate (NULL , kCFNumberSInt32Type , &width),
93
+ CFNumberCreate (NULL , kCFNumberSInt32Type , &height)};
94
+
95
+ CFDictionaryRef outputConfiguration = CFDictionaryCreate (NULL ,
96
+ outputKeys,
97
+ outputValues,
98
+ 3 ,
99
+ &kCFTypeDictionaryKeyCallBacks ,
100
+ &kCFTypeDictionaryValueCallBacks );
101
+
102
+ VTDecompressionOutputCallbackRecord callback = {&VTRgbPacketProcessorImpl::decodeFrame, NULL };
103
+
104
+ VTDecompressionSessionCreate (NULL , format, decoderSpecification, outputConfiguration, &callback, &decoder);
105
+
106
+ CFRelease (decoderSpecification);
107
+ CFRelease (outputConfiguration);
108
+ }
109
+
110
+ ~VTRgbPacketProcessorImpl () {
111
+ VTDecompressionSessionInvalidate (decoder);
112
+ CFRelease (decoder);
113
+ CFRelease (format);
114
+ }
115
+
116
+ static void decodeFrame (void *decompressionOutputRefCon,
117
+ void *sourceFrameRefCon,
118
+ OSStatus status,
119
+ VTDecodeInfoFlags infoFlags,
120
+ CVImageBufferRef pixelBuffer,
121
+ CMTime presentationTimeStamp,
122
+ CMTime presentationDuration) {
123
+ CVPixelBufferRef *outputPixelBuffer = (CVPixelBufferRef *) sourceFrameRefCon;
124
+ *outputPixelBuffer = CVPixelBufferRetain (pixelBuffer);
125
+ }
126
+
127
+ void startTiming () {
128
+ timer.start ();
129
+ }
130
+
131
+ void stopTiming () {
132
+ timing_acc += timer.stop ();
133
+ timing_acc_n += 1.0 ;
134
+
135
+ if (timing_acc_n >= 100.0 ) {
136
+ double avg = (timing_acc / timing_acc_n);
137
+ std::cout << " [VTRgbPacketProcessor] avg. time: " << (avg * 1000 ) << " ms -> ~" << (1.0 / avg) << " Hz"
138
+ << std::endl;
139
+ timing_acc = 0.0 ;
140
+ timing_acc_n = 0.0 ;
141
+ }
142
+ }
143
+ };
144
+
145
+ VTRgbPacketProcessor::VTRgbPacketProcessor () :
146
+ impl_ (new VTRgbPacketProcessorImpl())
147
+ {
148
+ }
149
+
150
+ VTRgbPacketProcessor::~VTRgbPacketProcessor ()
151
+ {
152
+ delete impl_;
153
+ }
154
+
155
+ void VTRgbPacketProcessor::process (const RgbPacket &packet)
156
+ {
157
+ if (listener_ != 0 ) {
158
+ impl_->startTiming ();
159
+
160
+ CMBlockBufferRef blockBuffer;
161
+ CMBlockBufferCreateWithMemoryBlock (
162
+ NULL ,
163
+ packet.jpeg_buffer ,
164
+ packet.jpeg_buffer_length ,
165
+ kCFAllocatorNull ,
166
+ NULL ,
167
+ 0 ,
168
+ packet.jpeg_buffer_length ,
169
+ 0 ,
170
+ &blockBuffer
171
+ );
172
+
173
+ CMSampleBufferRef sampleBuffer;
174
+ CMSampleBufferCreateReady (
175
+ NULL ,
176
+ blockBuffer,
177
+ impl_->format ,
178
+ 1 ,
179
+ 0 ,
180
+ NULL ,
181
+ 0 ,
182
+ NULL ,
183
+ &sampleBuffer
184
+ );
185
+
186
+ CVPixelBufferRef pixelBuffer = NULL ;
187
+ VTDecompressionSessionDecodeFrame (impl_->decoder , sampleBuffer, 0 , &pixelBuffer, NULL );
188
+
189
+ Frame *frame = new VTFrame (1920 , 1080 , 4 , pixelBuffer);
190
+
191
+ frame->timestamp = packet.timestamp ;
192
+ frame->sequence = packet.sequence ;
193
+
194
+ listener_->onNewFrame (Frame::Color, frame);
195
+
196
+ CFRelease (sampleBuffer);
197
+ CFRelease (blockBuffer);
198
+
199
+ impl_->stopTiming ();
200
+ }
201
+ }
202
+
203
+ } /* namespace libfreenect2 */
0 commit comments