19#include "capture_policy.h"
20#include <winpr/assert.h>
21#include <VideoToolbox/VideoToolbox.h>
23OSStatus cam_avfoundation_pixel_transfer_create(CFTypeRef* transfer)
25 WINPR_ASSERT(transfer);
27 VTPixelTransferSessionRef session = NULL;
28 OSStatus status = VTPixelTransferSessionCreate(NULL, &session);
32 CFNumberRef spacing = CFNumberCreate(NULL, kCFNumberIntType, &one);
33 CFDictionaryRef aspect = NULL;
36 const void* keys[] = { kCVImageBufferPixelAspectRatioHorizontalSpacingKey,
37 kCVImageBufferPixelAspectRatioVerticalSpacingKey };
38 const void* values[] = { spacing, spacing };
39 aspect = CFDictionaryCreate(NULL, keys, values, 2, &kCFTypeDictionaryKeyCallBacks,
40 &kCFTypeDictionaryValueCallBacks);
44 status = kVTAllocationFailedErr;
49 status = VTSessionSetProperty(session, kVTPixelTransferPropertyKey_ScalingMode,
50 kVTScalingMode_Letterbox);
52 status = VTSessionSetProperty(
53 session, kVTPixelTransferPropertyKey_DestinationPixelAspectRatio, aspect);
65BOOL cam_avfoundation_pixel_buffer_to_nv12(CVPixelBufferRef image,
wStream* output)
69 if ((CVPixelBufferGetPixelFormatType(image) !=
70 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) ||
71 (CVPixelBufferGetPlaneCount(image) != 2))
73 const size_t width = CVPixelBufferGetWidth(image);
74 const size_t height = CVPixelBufferGetHeight(image);
75 if (!width || !height || (width % 2) || (height % 2) || (width > CAM_AVFOUNDATION_MAX_WIDTH) ||
76 (height > CAM_AVFOUNDATION_MAX_HEIGHT))
78 if ((CVPixelBufferGetHeightOfPlane(image, 0) != height) ||
79 (CVPixelBufferGetHeightOfPlane(image, 1) != height / 2) ||
80 (CVPixelBufferGetBytesPerRowOfPlane(image, 0) < width) ||
81 (CVPixelBufferGetBytesPerRowOfPlane(image, 1) < width))
83 Stream_ResetPosition(output);
84 if (!Stream_EnsureRemainingCapacity(output, width * height * 3 / 2) ||
85 (CVPixelBufferLockBaseAddress(image, kCVPixelBufferLock_ReadOnly) != kCVReturnSuccess))
87 for (
size_t plane = 0; plane < 2; plane++)
89 const BYTE* data = CVPixelBufferGetBaseAddressOfPlane(image, plane);
90 const size_t stride = CVPixelBufferGetBytesPerRowOfPlane(image, plane);
93 CVPixelBufferUnlockBaseAddress(image, kCVPixelBufferLock_ReadOnly);
96 for (
size_t row = 0; row < CVPixelBufferGetHeightOfPlane(image, plane); row++)
97 Stream_Write(output, data + row * stride, width);
99 CVPixelBufferUnlockBaseAddress(image, kCVPixelBufferLock_ReadOnly);
100 Stream_SealLength(output);