• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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