1/* 2 * Customer wrappers for a number of CoreVideo APIs. 3 */ 4#include <Python.h> 5#include "pyobjc-api.h" 6 7#if PyObjC_BUILD_RELEASE >= 1005 8 /* WITH_COREVIDEO */ 9 10#import <CoreVideo/CoreVideo.h> 11 12static void 13mod_CVPixelBufferReleaseBytesCallback( 14 void *releaseRefCon, const void *baseAddress) 15{ 16 PyObject* info = (PyObject*)releaseRefCon; 17 PyGILState_STATE state = PyGILState_Ensure(); 18 19 if (PyTuple_GET_ITEM(info, 0) != Py_None) { 20 PyObject* r = PyObject_CallFunction( 21 PyTuple_GET_ITEM(info, 0), 22 "O", 23 PyTuple_GET_ITEM(info, 1)); 24 if (r == NULL) { 25 Py_XDECREF(info); 26 PyObjCErr_ToObjCWithGILState(&state); 27 } 28 29 Py_DECREF(r); 30 } 31 32 Py_DECREF(info); 33 PyGILState_Release(state); 34} 35 36static PyObject* 37mod_CVPixelBufferCreateWithBytes( 38 PyObject* self __attribute__((__unused__)), 39 PyObject* args) 40{ 41 CFAllocatorRef allocator; 42 size_t width; 43 size_t height; 44 OSType pixelFormatType; 45 void* baseAddress; 46 size_t bytesPerRow; 47 CFDictionaryRef pixelBufferAttributes; 48 CVPixelBufferRef pixelBuffer; 49 PyObject* py_allocator; 50 PyObject* py_width; 51 PyObject* py_height; 52 PyObject* py_pixelFormatType; 53 PyObject* py_buffer; 54 Py_ssize_t buflen; 55 PyObject* py_bytesPerRow; 56 PyObject* releaseCallback; 57 PyObject* info; 58 PyObject* py_pixelBufferAttributes; 59 PyObject* py_pixelBuffer = Py_None; 60 61 if (!PyArg_ParseTuple(args, "OOOOOOOOO|O", 62 &py_allocator, &py_width, &py_height, &py_pixelFormatType, 63 &py_buffer, &py_bytesPerRow, &releaseCallback, &info, 64 &py_pixelBufferAttributes, &py_pixelBuffer)) { 65 66 return NULL; 67 } 68 69 if (PyObjC_PythonToObjC(@encode(CFAllocatorRef), py_allocator, &allocator) < 0) { 70 return NULL; 71 } 72 if (PyObjC_PythonToObjC(@encode(size_t), py_width, &width) < 0) { 73 return NULL; 74 } 75 if (PyObjC_PythonToObjC(@encode(size_t), py_height, &height) < 0) { 76 return NULL; 77 } 78 if (PyObjC_PythonToObjC(@encode(OSType), py_pixelFormatType, &pixelFormatType) < 0) { 79 return NULL; 80 } 81 if (PyObjC_PythonToObjC(@encode(size_t), py_bytesPerRow, &bytesPerRow) < 0) { 82 return NULL; 83 } 84 if (PyObjC_PythonToObjC(@encode(CFDictionaryRef), py_pixelBufferAttributes, &pixelBufferAttributes) < 0) { 85 return NULL; 86 } 87 88 if (py_pixelBuffer != Py_None) { 89 PyErr_SetString(PyExc_ValueError, "pixelBufferOut must be None"); 90 return NULL; 91 } 92 93 if (PyObject_AsWriteBuffer(py_buffer, &baseAddress, &buflen) < 0) { 94 return NULL; 95 } 96 97 PyObject* real_info = Py_BuildValue("OOO", 98 releaseCallback, info, py_buffer); 99 if (real_info == NULL) { 100 return NULL; 101 } 102 103 CVReturn rv; 104 105 PyObjC_DURING 106 rv = CVPixelBufferCreateWithBytes( 107 allocator, 108 width, 109 height, 110 pixelFormatType, 111 baseAddress, 112 bytesPerRow, 113 mod_CVPixelBufferReleaseBytesCallback, 114 real_info, 115 pixelBufferAttributes, 116 &pixelBuffer); 117 118 PyObjC_HANDLER 119 rv = 0; 120 PyObjCErr_FromObjC(localException); 121 122 PyObjC_ENDHANDLER 123 124 if (PyErr_Occurred()) { 125 Py_DECREF(real_info); 126 return NULL; 127 } 128 129 if (pixelBuffer == NULL) { 130 Py_DECREF(real_info); 131 Py_INCREF(Py_None); 132 return Py_None; 133 } 134 135 py_pixelBuffer = PyObjC_ObjCToPython( 136 @encode(CVPixelBufferRef), 137 &pixelBuffer); 138 CFRelease(pixelBuffer); /* Compensate for create rule */ 139 return py_pixelBuffer; 140} 141 142 143 144static PyMethodDef mod_methods[] = { 145 { 146 "CVPixelBufferCreateWithBytes", 147 (PyCFunction)mod_CVPixelBufferCreateWithBytes, 148 METH_VARARGS, 149 NULL 150 }, 151 152 { 0, 0, 0, 0 } 153}; 154 155#else /* ! WITH_CORE_VIDEO */ 156 157static PyMethodDef mod_methods[] = { 158 { 0, 0, 0, 0 } 159}; 160 161#endif /* ! WITH_CORE_VIDEO */ 162 163 164 165PyObjC_MODULE_INIT(_CVPixelBuffer) 166{ 167 PyObject* m = PyObjC_MODULE_CREATE(_CVPixelBuffer); 168 if (!m) PyObjC_INITERROR(); 169 170 if (PyObjC_ImportAPI(m) < 0) PyObjC_INITERROR(); 171 172 PyObjC_INITDONE(); 173} 174