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 37static 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 51CFDictionaryRef 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 72QTPixelBuffer::QTPixelBuffer() 73 : m_pixelBuffer(0) 74{ 75} 76 77QTPixelBuffer::QTPixelBuffer(const QTPixelBuffer& p) 78 : m_pixelBuffer(p.m_pixelBuffer) 79{ 80 CVPixelBufferRetain(m_pixelBuffer); 81} 82 83QTPixelBuffer::QTPixelBuffer(CVPixelBufferRef ref) 84 : m_pixelBuffer(ref) 85{ 86 CVPixelBufferRetain(m_pixelBuffer); 87} 88 89QTPixelBuffer::~QTPixelBuffer() 90{ 91 clear(); 92} 93 94QTPixelBuffer& QTPixelBuffer::operator=(const QTPixelBuffer& p) 95{ 96 set(p.m_pixelBuffer); 97 return *this; 98} 99 100void QTPixelBuffer::set(CVPixelBufferRef ref) 101{ 102 CVPixelBufferRetain(ref); 103 CVPixelBufferRelease(m_pixelBuffer); 104 m_pixelBuffer = ref; 105} 106 107CVPixelBufferRef QTPixelBuffer::pixelBufferRef() 108{ 109 return m_pixelBuffer; 110} 111 112void QTPixelBuffer::adopt(CVPixelBufferRef ref) 113{ 114 if (ref == m_pixelBuffer) 115 return; 116 CVPixelBufferRelease(m_pixelBuffer); 117 m_pixelBuffer = ref; 118} 119 120void QTPixelBuffer::clear() 121{ 122 CVPixelBufferRelease(m_pixelBuffer); 123 m_pixelBuffer = 0; 124} 125 126CVReturn QTPixelBuffer::lockBaseAddress() 127{ 128 return CVPixelBufferLockBaseAddress(m_pixelBuffer, 0); 129} 130 131CVReturn QTPixelBuffer::unlockBaseAddress() 132{ 133 return CVPixelBufferUnlockBaseAddress(m_pixelBuffer, 0); 134} 135 136void* QTPixelBuffer::baseAddress() 137{ 138 return CVPixelBufferGetBaseAddress(m_pixelBuffer); 139} 140 141size_t QTPixelBuffer::width() const 142{ 143 return CVPixelBufferGetWidth(m_pixelBuffer); 144} 145 146size_t QTPixelBuffer::height() const 147{ 148 return CVPixelBufferGetHeight(m_pixelBuffer); 149} 150 151unsigned long QTPixelBuffer::pixelFormatType() const 152{ 153 return CVPixelBufferGetPixelFormatType(m_pixelBuffer); 154} 155 156bool QTPixelBuffer::pixelFormatIs32ARGB() const 157{ 158 return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32ARGBPixelFormat; 159} 160 161bool QTPixelBuffer::pixelFormatIs32BGRA() const 162{ 163 return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32BGRAPixelFormat; 164} 165 166size_t QTPixelBuffer::bytesPerRow() const 167{ 168 return CVPixelBufferGetBytesPerRow(m_pixelBuffer); 169} 170 171size_t QTPixelBuffer::dataSize() const 172{ 173 return CVPixelBufferGetDataSize(m_pixelBuffer); 174} 175 176bool QTPixelBuffer::isPlanar() const 177{ 178 return CVPixelBufferIsPlanar(m_pixelBuffer); 179} 180 181size_t QTPixelBuffer::planeCount() const 182{ 183 return CVPixelBufferGetPlaneCount(m_pixelBuffer); 184} 185 186size_t QTPixelBuffer::widthOfPlane(size_t plane) const 187{ 188 return CVPixelBufferGetWidthOfPlane(m_pixelBuffer, plane); 189} 190 191size_t QTPixelBuffer::heightOfPlane(size_t plane) const 192{ 193 return CVPixelBufferGetHeightOfPlane(m_pixelBuffer, plane); 194} 195 196void* QTPixelBuffer::baseAddressOfPlane(size_t plane) const 197{ 198 return CVPixelBufferGetBaseAddressOfPlane(m_pixelBuffer, plane); 199} 200 201size_t QTPixelBuffer::bytesPerRowOfPlane(size_t plane) const 202{ 203 return CVPixelBufferGetBytesPerRowOfPlane(m_pixelBuffer, plane); 204} 205 206void 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 211CFDictionaryRef QTPixelBuffer::attachments() const 212{ 213 return CVBufferGetAttachments(m_pixelBuffer, kCVAttachmentMode_ShouldPropagate); 214} 215 216void QTPixelBuffer::retainCallback(void* refcon) 217{ 218 CVPixelBufferRetain(static_cast<CVPixelBufferRef>(refcon)); 219} 220 221void QTPixelBuffer::releaseCallback(void* refcon) 222{ 223 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon)); 224} 225 226void QTPixelBuffer::imageQueueReleaseCallback(unsigned int type, uint64_t id, void* refcon) 227{ 228 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon)); 229} 230 231void QTPixelBuffer::dataProviderReleaseBytePointerCallback(void* refcon, const void* pointer) 232{ 233 CVPixelBufferUnlockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0); 234} 235 236const void* QTPixelBuffer::dataProviderGetBytePointerCallback(void* refcon) 237{ 238 CVPixelBufferLockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0); 239 return CVPixelBufferGetBaseAddress(static_cast<CVPixelBufferRef>(refcon)); 240} 241 242size_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 253void QTPixelBuffer::dataProviderReleaseInfoCallback(void* refcon) 254{ 255 CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon)); 256} 257