1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25 #include "config.h"
26
27 #include "QTPixelBuffer.h"
28
29 #include <CFNumber.h>
30 #include <CFString.h>
31 #include <CGColorSpace.h>
32 #include <CGImage.h>
33 #include <CVPixelBuffer.h>
34 #include <QuickDraw.h>
35 #include <memory.h>
36
SetNumberValue(CFMutableDictionaryRef inDict,CFStringRef inKey,SInt32 inValue)37 static OSStatus SetNumberValue(CFMutableDictionaryRef inDict, CFStringRef inKey, SInt32 inValue)
38 {
39 CFNumberRef number;
40
41 number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
42 if (!number)
43 return coreFoundationUnknownErr;
44
45 CFDictionarySetValue(inDict, inKey, number);
46 CFRelease(number);
47
48 return noErr;
49 }
50
createPixelBufferAttributesDictionary(QTPixelBuffer::Type contextType)51 CFDictionaryRef QTPixelBuffer::createPixelBufferAttributesDictionary(QTPixelBuffer::Type contextType)
52 {
53 static const CFStringRef kDirect3DCompatibilityKey = CFSTR("Direct3DCompatibility");
54
55 CFMutableDictionaryRef pixelBufferAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
56 if (contextType == QTPixelBuffer::ConfigureForCAImageQueue) {
57 // Ask for D3D compatible pixel buffers so no further work is needed.
58 CFDictionarySetValue(pixelBufferAttributes, kDirect3DCompatibilityKey, kCFBooleanTrue);
59 } else {
60 // Use the k32BGRAPixelFormat, as QuartzCore will be able to use the pixels directly,
61 // without needing an additional copy or rendering pass.
62 SetNumberValue(pixelBufferAttributes, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat);
63
64 // Set kCVPixelBufferBytesPerRowAlignmentKey to 16 to ensure that each row of pixels
65 // starts at a 16 byte aligned address for most efficient data reading.
66 SetNumberValue(pixelBufferAttributes, kCVPixelBufferBytesPerRowAlignmentKey, 16);
67 CFDictionarySetValue(pixelBufferAttributes, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanTrue);
68 }
69 return pixelBufferAttributes;
70 }
71
QTPixelBuffer()72 QTPixelBuffer::QTPixelBuffer()
73 : m_pixelBuffer(0)
74 {
75 }
76
QTPixelBuffer(const QTPixelBuffer & p)77 QTPixelBuffer::QTPixelBuffer(const QTPixelBuffer& p)
78 : m_pixelBuffer(p.m_pixelBuffer)
79 {
80 CVPixelBufferRetain(m_pixelBuffer);
81 }
82
QTPixelBuffer(CVPixelBufferRef ref)83 QTPixelBuffer::QTPixelBuffer(CVPixelBufferRef ref)
84 : m_pixelBuffer(ref)
85 {
86 CVPixelBufferRetain(m_pixelBuffer);
87 }
88
~QTPixelBuffer()89 QTPixelBuffer::~QTPixelBuffer()
90 {
91 clear();
92 }
93
operator =(const QTPixelBuffer & p)94 QTPixelBuffer& QTPixelBuffer::operator=(const QTPixelBuffer& p)
95 {
96 set(p.m_pixelBuffer);
97 return *this;
98 }
99
set(CVPixelBufferRef ref)100 void QTPixelBuffer::set(CVPixelBufferRef ref)
101 {
102 CVPixelBufferRetain(ref);
103 CVPixelBufferRelease(m_pixelBuffer);
104 m_pixelBuffer = ref;
105 }
106
pixelBufferRef()107 CVPixelBufferRef QTPixelBuffer::pixelBufferRef()
108 {
109 return m_pixelBuffer;
110 }
111
adopt(CVPixelBufferRef ref)112 void QTPixelBuffer::adopt(CVPixelBufferRef ref)
113 {
114 if (ref == m_pixelBuffer)
115 return;
116 CVPixelBufferRelease(m_pixelBuffer);
117 m_pixelBuffer = ref;
118 }
119
clear()120 void QTPixelBuffer::clear()
121 {
122 CVPixelBufferRelease(m_pixelBuffer);
123 m_pixelBuffer = 0;
124 }
125
lockBaseAddress()126 CVReturn QTPixelBuffer::lockBaseAddress()
127 {
128 return CVPixelBufferLockBaseAddress(m_pixelBuffer, 0);
129 }
130
unlockBaseAddress()131 CVReturn QTPixelBuffer::unlockBaseAddress()
132 {
133 return CVPixelBufferUnlockBaseAddress(m_pixelBuffer, 0);
134 }
135
baseAddress()136 void* QTPixelBuffer::baseAddress()
137 {
138 return CVPixelBufferGetBaseAddress(m_pixelBuffer);
139 }
140
width() const141 size_t QTPixelBuffer::width() const
142 {
143 return CVPixelBufferGetWidth(m_pixelBuffer);
144 }
145
height() const146 size_t QTPixelBuffer::height() const
147 {
148 return CVPixelBufferGetHeight(m_pixelBuffer);
149 }
150
pixelFormatType() const151 unsigned long QTPixelBuffer::pixelFormatType() const
152 {
153 return CVPixelBufferGetPixelFormatType(m_pixelBuffer);
154 }
155
pixelFormatIs32ARGB() const156 bool QTPixelBuffer::pixelFormatIs32ARGB() const
157 {
158 return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32ARGBPixelFormat;
159 }
160
pixelFormatIs32BGRA() const161 bool QTPixelBuffer::pixelFormatIs32BGRA() const
162 {
163 return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32BGRAPixelFormat;
164 }
165
bytesPerRow() const166 size_t QTPixelBuffer::bytesPerRow() const
167 {
168 return CVPixelBufferGetBytesPerRow(m_pixelBuffer);
169 }
170
dataSize() const171 size_t QTPixelBuffer::dataSize() const
172 {
173 return CVPixelBufferGetDataSize(m_pixelBuffer);
174 }
175
isPlanar() const176 bool QTPixelBuffer::isPlanar() const
177 {
178 return CVPixelBufferIsPlanar(m_pixelBuffer);
179 }
180
planeCount() const181 size_t QTPixelBuffer::planeCount() const
182 {
183 return CVPixelBufferGetPlaneCount(m_pixelBuffer);
184 }
185
widthOfPlane(size_t plane) const186 size_t QTPixelBuffer::widthOfPlane(size_t plane) const
187 {
188 return CVPixelBufferGetWidthOfPlane(m_pixelBuffer, plane);
189 }
190
heightOfPlane(size_t plane) const191 size_t QTPixelBuffer::heightOfPlane(size_t plane) const
192 {
193 return CVPixelBufferGetHeightOfPlane(m_pixelBuffer, plane);
194 }
195
baseAddressOfPlane(size_t plane) const196 void* QTPixelBuffer::baseAddressOfPlane(size_t plane) const
197 {
198 return CVPixelBufferGetBaseAddressOfPlane(m_pixelBuffer, plane);
199 }
200
bytesPerRowOfPlane(size_t plane) const201 size_t QTPixelBuffer::bytesPerRowOfPlane(size_t plane) const
202 {
203 return CVPixelBufferGetBytesPerRowOfPlane(m_pixelBuffer, plane);
204 }
205
getExtendedPixels(size_t * left,size_t * right,size_t * top,size_t * bottom) const206 void QTPixelBuffer::getExtendedPixels(size_t* left, size_t* right, size_t* top, size_t* bottom) const
207 {
208 return CVPixelBufferGetExtendedPixels(m_pixelBuffer, left, right, top, bottom);
209 }
210
attachments() const211 CFDictionaryRef QTPixelBuffer::attachments() const
212 {
213 return CVBufferGetAttachments(m_pixelBuffer, kCVAttachmentMode_ShouldPropagate);
214 }
215
retainCallback(void * refcon)216 void QTPixelBuffer::retainCallback(void* refcon)
217 {
218 CVPixelBufferRetain(static_cast<CVPixelBufferRef>(refcon));
219 }
220
releaseCallback(void * refcon)221 void QTPixelBuffer::releaseCallback(void* refcon)
222 {
223 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
224 }
225
imageQueueReleaseCallback(unsigned int type,uint64_t id,void * refcon)226 void QTPixelBuffer::imageQueueReleaseCallback(unsigned int type, uint64_t id, void* refcon)
227 {
228 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
229 }
230
dataProviderReleaseBytePointerCallback(void * refcon,const void * pointer)231 void QTPixelBuffer::dataProviderReleaseBytePointerCallback(void* refcon, const void* pointer)
232 {
233 CVPixelBufferUnlockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0);
234 }
235
dataProviderGetBytePointerCallback(void * refcon)236 const void* QTPixelBuffer::dataProviderGetBytePointerCallback(void* refcon)
237 {
238 CVPixelBufferLockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0);
239 return CVPixelBufferGetBaseAddress(static_cast<CVPixelBufferRef>(refcon));
240 }
241
dataProviderGetBytesAtPositionCallback(void * refcon,void * buffer,size_t position,size_t count)242 size_t QTPixelBuffer::dataProviderGetBytesAtPositionCallback(void* refcon, void* buffer, size_t position, size_t count)
243 {
244 char* data = (char*)CVPixelBufferGetBaseAddress(static_cast<CVPixelBufferRef>(refcon));
245 size_t size = CVPixelBufferGetDataSize(static_cast<CVPixelBufferRef>(refcon));
246 if (size - position < count)
247 count = size - position;
248
249 memcpy(buffer, data+position, count);
250 return count;
251 }
252
dataProviderReleaseInfoCallback(void * refcon)253 void QTPixelBuffer::dataProviderReleaseInfoCallback(void* refcon)
254 {
255 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
256 }
257