1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "config.h" 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <stdint.h> 22cabdff1aSopenharmony_ci#include <string.h> 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include <VideoToolbox/VideoToolbox.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "buffer.h" 27cabdff1aSopenharmony_ci#include "buffer_internal.h" 28cabdff1aSopenharmony_ci#include "common.h" 29cabdff1aSopenharmony_ci#include "hwcontext.h" 30cabdff1aSopenharmony_ci#include "hwcontext_internal.h" 31cabdff1aSopenharmony_ci#include "hwcontext_videotoolbox.h" 32cabdff1aSopenharmony_ci#include "mem.h" 33cabdff1aSopenharmony_ci#include "pixfmt.h" 34cabdff1aSopenharmony_ci#include "pixdesc.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_citypedef struct VTFramesContext { 37cabdff1aSopenharmony_ci CVPixelBufferPoolRef pool; 38cabdff1aSopenharmony_ci} VTFramesContext; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic const struct { 41cabdff1aSopenharmony_ci uint32_t cv_fmt; 42cabdff1aSopenharmony_ci bool full_range; 43cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt; 44cabdff1aSopenharmony_ci} cv_pix_fmts[] = { 45cabdff1aSopenharmony_ci { kCVPixelFormatType_420YpCbCr8Planar, false, AV_PIX_FMT_YUV420P }, 46cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr8, false, AV_PIX_FMT_UYVY422 }, 47cabdff1aSopenharmony_ci { kCVPixelFormatType_32BGRA, false, AV_PIX_FMT_BGRA }, 48cabdff1aSopenharmony_ci#ifdef kCFCoreFoundationVersionNumber10_7 49cabdff1aSopenharmony_ci { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV12 }, 50cabdff1aSopenharmony_ci { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV12 }, 51cabdff1aSopenharmony_ci { kCVPixelFormatType_4444AYpCbCr16, false, AV_PIX_FMT_AYUV64 }, 52cabdff1aSopenharmony_ci#endif 53cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE 54cabdff1aSopenharmony_ci { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P010 }, 55cabdff1aSopenharmony_ci { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P010 }, 56cabdff1aSopenharmony_ci#endif 57cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE 58cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV16 }, 59cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV16 }, 60cabdff1aSopenharmony_ci#endif 61cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE 62cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P210 }, 63cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P210 }, 64cabdff1aSopenharmony_ci#endif 65cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE 66cabdff1aSopenharmony_ci { kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P216 }, 67cabdff1aSopenharmony_ci#endif 68cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE 69cabdff1aSopenharmony_ci { kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV24 }, 70cabdff1aSopenharmony_ci { kCVPixelFormatType_444YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV24 }, 71cabdff1aSopenharmony_ci#endif 72cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE 73cabdff1aSopenharmony_ci { kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P410 }, 74cabdff1aSopenharmony_ci { kCVPixelFormatType_444YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P410 }, 75cabdff1aSopenharmony_ci#endif 76cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE 77cabdff1aSopenharmony_ci { kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P416 }, 78cabdff1aSopenharmony_ci#endif 79cabdff1aSopenharmony_ci}; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_cistatic const enum AVPixelFormat supported_formats[] = { 82cabdff1aSopenharmony_ci#ifdef kCFCoreFoundationVersionNumber10_7 83cabdff1aSopenharmony_ci AV_PIX_FMT_NV12, 84cabdff1aSopenharmony_ci AV_PIX_FMT_AYUV64, 85cabdff1aSopenharmony_ci#endif 86cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 87cabdff1aSopenharmony_ci AV_PIX_FMT_UYVY422, 88cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE 89cabdff1aSopenharmony_ci AV_PIX_FMT_P010, 90cabdff1aSopenharmony_ci#endif 91cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE 92cabdff1aSopenharmony_ci AV_PIX_FMT_NV16, 93cabdff1aSopenharmony_ci#endif 94cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE 95cabdff1aSopenharmony_ci AV_PIX_FMT_P210, 96cabdff1aSopenharmony_ci#endif 97cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE 98cabdff1aSopenharmony_ci AV_PIX_FMT_P216, 99cabdff1aSopenharmony_ci#endif 100cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE 101cabdff1aSopenharmony_ci AV_PIX_FMT_NV24, 102cabdff1aSopenharmony_ci#endif 103cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE 104cabdff1aSopenharmony_ci AV_PIX_FMT_P410, 105cabdff1aSopenharmony_ci#endif 106cabdff1aSopenharmony_ci#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE 107cabdff1aSopenharmony_ci AV_PIX_FMT_P416, 108cabdff1aSopenharmony_ci#endif 109cabdff1aSopenharmony_ci AV_PIX_FMT_BGRA, 110cabdff1aSopenharmony_ci}; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_cistatic int vt_frames_get_constraints(AVHWDeviceContext *ctx, 113cabdff1aSopenharmony_ci const void *hwconfig, 114cabdff1aSopenharmony_ci AVHWFramesConstraints *constraints) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci int i; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1, 119cabdff1aSopenharmony_ci sizeof(*constraints->valid_sw_formats)); 120cabdff1aSopenharmony_ci if (!constraints->valid_sw_formats) 121cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) 124cabdff1aSopenharmony_ci constraints->valid_sw_formats[i] = supported_formats[i]; 125cabdff1aSopenharmony_ci constraints->valid_sw_formats[FF_ARRAY_ELEMS(supported_formats)] = AV_PIX_FMT_NONE; 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); 128cabdff1aSopenharmony_ci if (!constraints->valid_hw_formats) 129cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci constraints->valid_hw_formats[0] = AV_PIX_FMT_VIDEOTOOLBOX; 132cabdff1aSopenharmony_ci constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci return 0; 135cabdff1aSopenharmony_ci} 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_cienum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt) 138cabdff1aSopenharmony_ci{ 139cabdff1aSopenharmony_ci int i; 140cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) { 141cabdff1aSopenharmony_ci if (cv_pix_fmts[i].cv_fmt == cv_fmt) 142cabdff1aSopenharmony_ci return cv_pix_fmts[i].pix_fmt; 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci return AV_PIX_FMT_NONE; 145cabdff1aSopenharmony_ci} 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ciuint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt) 148cabdff1aSopenharmony_ci{ 149cabdff1aSopenharmony_ci return av_map_videotoolbox_format_from_pixfmt2(pix_fmt, false); 150cabdff1aSopenharmony_ci} 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ciuint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range) 153cabdff1aSopenharmony_ci{ 154cabdff1aSopenharmony_ci int i; 155cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) { 156cabdff1aSopenharmony_ci if (cv_pix_fmts[i].pix_fmt == pix_fmt && cv_pix_fmts[i].full_range == full_range) 157cabdff1aSopenharmony_ci return cv_pix_fmts[i].cv_fmt; 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci return 0; 160cabdff1aSopenharmony_ci} 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_cistatic int vt_pool_alloc(AVHWFramesContext *ctx) 163cabdff1aSopenharmony_ci{ 164cabdff1aSopenharmony_ci VTFramesContext *fctx = ctx->internal->priv; 165cabdff1aSopenharmony_ci CVReturn err; 166cabdff1aSopenharmony_ci CFNumberRef w, h, pixfmt; 167cabdff1aSopenharmony_ci uint32_t cv_pixfmt; 168cabdff1aSopenharmony_ci CFMutableDictionaryRef attributes, iosurface_properties; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci attributes = CFDictionaryCreateMutable( 171cabdff1aSopenharmony_ci NULL, 172cabdff1aSopenharmony_ci 2, 173cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 174cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci cv_pixfmt = av_map_videotoolbox_format_from_pixfmt(ctx->sw_format); 177cabdff1aSopenharmony_ci pixfmt = CFNumberCreate(NULL, kCFNumberSInt32Type, &cv_pixfmt); 178cabdff1aSopenharmony_ci CFDictionarySetValue( 179cabdff1aSopenharmony_ci attributes, 180cabdff1aSopenharmony_ci kCVPixelBufferPixelFormatTypeKey, 181cabdff1aSopenharmony_ci pixfmt); 182cabdff1aSopenharmony_ci CFRelease(pixfmt); 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci iosurface_properties = CFDictionaryCreateMutable( 185cabdff1aSopenharmony_ci NULL, 186cabdff1aSopenharmony_ci 0, 187cabdff1aSopenharmony_ci &kCFTypeDictionaryKeyCallBacks, 188cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 189cabdff1aSopenharmony_ci CFDictionarySetValue(attributes, kCVPixelBufferIOSurfacePropertiesKey, iosurface_properties); 190cabdff1aSopenharmony_ci CFRelease(iosurface_properties); 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci w = CFNumberCreate(NULL, kCFNumberSInt32Type, &ctx->width); 193cabdff1aSopenharmony_ci h = CFNumberCreate(NULL, kCFNumberSInt32Type, &ctx->height); 194cabdff1aSopenharmony_ci CFDictionarySetValue(attributes, kCVPixelBufferWidthKey, w); 195cabdff1aSopenharmony_ci CFDictionarySetValue(attributes, kCVPixelBufferHeightKey, h); 196cabdff1aSopenharmony_ci CFRelease(w); 197cabdff1aSopenharmony_ci CFRelease(h); 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci err = CVPixelBufferPoolCreate( 200cabdff1aSopenharmony_ci NULL, 201cabdff1aSopenharmony_ci NULL, 202cabdff1aSopenharmony_ci attributes, 203cabdff1aSopenharmony_ci &fctx->pool); 204cabdff1aSopenharmony_ci CFRelease(attributes); 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (err == kCVReturnSuccess) 207cabdff1aSopenharmony_ci return 0; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error creating CVPixelBufferPool: %d\n", err); 210cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 211cabdff1aSopenharmony_ci} 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_cistatic void videotoolbox_buffer_release(void *opaque, uint8_t *data) 214cabdff1aSopenharmony_ci{ 215cabdff1aSopenharmony_ci CVPixelBufferRelease((CVPixelBufferRef)data); 216cabdff1aSopenharmony_ci} 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_cistatic AVBufferRef *vt_pool_alloc_buffer(void *opaque, size_t size) 219cabdff1aSopenharmony_ci{ 220cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf; 221cabdff1aSopenharmony_ci AVBufferRef *buf; 222cabdff1aSopenharmony_ci CVReturn err; 223cabdff1aSopenharmony_ci AVHWFramesContext *ctx = opaque; 224cabdff1aSopenharmony_ci VTFramesContext *fctx = ctx->internal->priv; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci err = CVPixelBufferPoolCreatePixelBuffer( 227cabdff1aSopenharmony_ci NULL, 228cabdff1aSopenharmony_ci fctx->pool, 229cabdff1aSopenharmony_ci &pixbuf 230cabdff1aSopenharmony_ci ); 231cabdff1aSopenharmony_ci if (err != kCVReturnSuccess) { 232cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Failed to create pixel buffer from pool: %d\n", err); 233cabdff1aSopenharmony_ci return NULL; 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci buf = av_buffer_create((uint8_t *)pixbuf, size, 237cabdff1aSopenharmony_ci videotoolbox_buffer_release, NULL, 0); 238cabdff1aSopenharmony_ci if (!buf) { 239cabdff1aSopenharmony_ci CVPixelBufferRelease(pixbuf); 240cabdff1aSopenharmony_ci return NULL; 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci return buf; 243cabdff1aSopenharmony_ci} 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_cistatic void vt_frames_uninit(AVHWFramesContext *ctx) 246cabdff1aSopenharmony_ci{ 247cabdff1aSopenharmony_ci VTFramesContext *fctx = ctx->internal->priv; 248cabdff1aSopenharmony_ci if (fctx->pool) { 249cabdff1aSopenharmony_ci CVPixelBufferPoolRelease(fctx->pool); 250cabdff1aSopenharmony_ci fctx->pool = NULL; 251cabdff1aSopenharmony_ci } 252cabdff1aSopenharmony_ci} 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_cistatic int vt_frames_init(AVHWFramesContext *ctx) 255cabdff1aSopenharmony_ci{ 256cabdff1aSopenharmony_ci int i, ret; 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { 259cabdff1aSopenharmony_ci if (ctx->sw_format == supported_formats[i]) 260cabdff1aSopenharmony_ci break; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci if (i == FF_ARRAY_ELEMS(supported_formats)) { 263cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n", 264cabdff1aSopenharmony_ci av_get_pix_fmt_name(ctx->sw_format)); 265cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci if (!ctx->pool) { 269cabdff1aSopenharmony_ci ctx->internal->pool_internal = av_buffer_pool_init2( 270cabdff1aSopenharmony_ci sizeof(CVPixelBufferRef), ctx, vt_pool_alloc_buffer, NULL); 271cabdff1aSopenharmony_ci if (!ctx->internal->pool_internal) 272cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci ret = vt_pool_alloc(ctx); 276cabdff1aSopenharmony_ci if (ret < 0) 277cabdff1aSopenharmony_ci return ret; 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci return 0; 280cabdff1aSopenharmony_ci} 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_cistatic int vt_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) 283cabdff1aSopenharmony_ci{ 284cabdff1aSopenharmony_ci frame->buf[0] = av_buffer_pool_get(ctx->pool); 285cabdff1aSopenharmony_ci if (!frame->buf[0]) 286cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci frame->data[3] = frame->buf[0]->data; 289cabdff1aSopenharmony_ci frame->format = AV_PIX_FMT_VIDEOTOOLBOX; 290cabdff1aSopenharmony_ci frame->width = ctx->width; 291cabdff1aSopenharmony_ci frame->height = ctx->height; 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci return 0; 294cabdff1aSopenharmony_ci} 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_cistatic int vt_transfer_get_formats(AVHWFramesContext *ctx, 297cabdff1aSopenharmony_ci enum AVHWFrameTransferDirection dir, 298cabdff1aSopenharmony_ci enum AVPixelFormat **formats) 299cabdff1aSopenharmony_ci{ 300cabdff1aSopenharmony_ci enum AVPixelFormat *fmts = av_malloc_array(2, sizeof(*fmts)); 301cabdff1aSopenharmony_ci if (!fmts) 302cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci fmts[0] = ctx->sw_format; 305cabdff1aSopenharmony_ci fmts[1] = AV_PIX_FMT_NONE; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci *formats = fmts; 308cabdff1aSopenharmony_ci return 0; 309cabdff1aSopenharmony_ci} 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_cistatic void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) 312cabdff1aSopenharmony_ci{ 313cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf = (CVPixelBufferRef)hwmap->source->data[3]; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv); 316cabdff1aSopenharmony_ci} 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_cistatic int vt_pixbuf_set_par(void *log_ctx, 319cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf, const AVFrame *src) 320cabdff1aSopenharmony_ci{ 321cabdff1aSopenharmony_ci CFMutableDictionaryRef par = NULL; 322cabdff1aSopenharmony_ci CFNumberRef num = NULL, den = NULL; 323cabdff1aSopenharmony_ci AVRational avpar = src->sample_aspect_ratio; 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci if (avpar.num == 0) 326cabdff1aSopenharmony_ci return 0; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci av_reduce(&avpar.num, &avpar.den, 329cabdff1aSopenharmony_ci avpar.num, avpar.den, 330cabdff1aSopenharmony_ci 0xFFFFFFFF); 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci num = CFNumberCreate(kCFAllocatorDefault, 333cabdff1aSopenharmony_ci kCFNumberIntType, 334cabdff1aSopenharmony_ci &avpar.num); 335cabdff1aSopenharmony_ci 336cabdff1aSopenharmony_ci den = CFNumberCreate(kCFAllocatorDefault, 337cabdff1aSopenharmony_ci kCFNumberIntType, 338cabdff1aSopenharmony_ci &avpar.den); 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci par = CFDictionaryCreateMutable(kCFAllocatorDefault, 341cabdff1aSopenharmony_ci 2, 342cabdff1aSopenharmony_ci &kCFCopyStringDictionaryKeyCallBacks, 343cabdff1aSopenharmony_ci &kCFTypeDictionaryValueCallBacks); 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci if (!par || !num || !den) { 346cabdff1aSopenharmony_ci if (par) CFRelease(par); 347cabdff1aSopenharmony_ci if (num) CFRelease(num); 348cabdff1aSopenharmony_ci if (den) CFRelease(den); 349cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci CFDictionarySetValue( 353cabdff1aSopenharmony_ci par, 354cabdff1aSopenharmony_ci kCVImageBufferPixelAspectRatioHorizontalSpacingKey, 355cabdff1aSopenharmony_ci num); 356cabdff1aSopenharmony_ci CFDictionarySetValue( 357cabdff1aSopenharmony_ci par, 358cabdff1aSopenharmony_ci kCVImageBufferPixelAspectRatioVerticalSpacingKey, 359cabdff1aSopenharmony_ci den); 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci CVBufferSetAttachment( 362cabdff1aSopenharmony_ci pixbuf, 363cabdff1aSopenharmony_ci kCVImageBufferPixelAspectRatioKey, 364cabdff1aSopenharmony_ci par, 365cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate 366cabdff1aSopenharmony_ci ); 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci CFRelease(par); 369cabdff1aSopenharmony_ci CFRelease(num); 370cabdff1aSopenharmony_ci CFRelease(den); 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci return 0; 373cabdff1aSopenharmony_ci} 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ciCFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc) 376cabdff1aSopenharmony_ci{ 377cabdff1aSopenharmony_ci switch (loc) { 378cabdff1aSopenharmony_ci case AVCHROMA_LOC_LEFT: 379cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_Left; 380cabdff1aSopenharmony_ci case AVCHROMA_LOC_CENTER: 381cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_Center; 382cabdff1aSopenharmony_ci case AVCHROMA_LOC_TOP: 383cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_Top; 384cabdff1aSopenharmony_ci case AVCHROMA_LOC_BOTTOM: 385cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_Bottom; 386cabdff1aSopenharmony_ci case AVCHROMA_LOC_TOPLEFT: 387cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_TopLeft; 388cabdff1aSopenharmony_ci case AVCHROMA_LOC_BOTTOMLEFT: 389cabdff1aSopenharmony_ci return kCVImageBufferChromaLocation_BottomLeft; 390cabdff1aSopenharmony_ci default: 391cabdff1aSopenharmony_ci return NULL; 392cabdff1aSopenharmony_ci } 393cabdff1aSopenharmony_ci} 394cabdff1aSopenharmony_ci 395cabdff1aSopenharmony_cistatic int vt_pixbuf_set_chromaloc(void *log_ctx, 396cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf, const AVFrame *src) 397cabdff1aSopenharmony_ci{ 398cabdff1aSopenharmony_ci CFStringRef loc = av_map_videotoolbox_chroma_loc_from_av(src->chroma_location); 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci if (loc) { 401cabdff1aSopenharmony_ci CVBufferSetAttachment( 402cabdff1aSopenharmony_ci pixbuf, 403cabdff1aSopenharmony_ci kCVImageBufferChromaLocationTopFieldKey, 404cabdff1aSopenharmony_ci loc, 405cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate); 406cabdff1aSopenharmony_ci } 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci return 0; 409cabdff1aSopenharmony_ci} 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ciCFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space) 412cabdff1aSopenharmony_ci{ 413cabdff1aSopenharmony_ci switch (space) { 414cabdff1aSopenharmony_ci case AVCOL_SPC_BT2020_CL: 415cabdff1aSopenharmony_ci case AVCOL_SPC_BT2020_NCL: 416cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020 417cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.11, iOS 9, *)) 418cabdff1aSopenharmony_ci return kCVImageBufferYCbCrMatrix_ITU_R_2020; 419cabdff1aSopenharmony_ci#endif 420cabdff1aSopenharmony_ci return CFSTR("ITU_R_2020"); 421cabdff1aSopenharmony_ci case AVCOL_SPC_BT470BG: 422cabdff1aSopenharmony_ci case AVCOL_SPC_SMPTE170M: 423cabdff1aSopenharmony_ci return kCVImageBufferYCbCrMatrix_ITU_R_601_4; 424cabdff1aSopenharmony_ci case AVCOL_SPC_BT709: 425cabdff1aSopenharmony_ci return kCVImageBufferYCbCrMatrix_ITU_R_709_2; 426cabdff1aSopenharmony_ci case AVCOL_SPC_SMPTE240M: 427cabdff1aSopenharmony_ci return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; 428cabdff1aSopenharmony_ci default: 429cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG 430cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) 431cabdff1aSopenharmony_ci return CVYCbCrMatrixGetStringForIntegerCodePoint(space); 432cabdff1aSopenharmony_ci#endif 433cabdff1aSopenharmony_ci case AVCOL_SPC_UNSPECIFIED: 434cabdff1aSopenharmony_ci return NULL; 435cabdff1aSopenharmony_ci } 436cabdff1aSopenharmony_ci} 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ciCFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri) 439cabdff1aSopenharmony_ci{ 440cabdff1aSopenharmony_ci switch (pri) { 441cabdff1aSopenharmony_ci case AVCOL_PRI_BT2020: 442cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020 443cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.11, iOS 9, *)) 444cabdff1aSopenharmony_ci return kCVImageBufferColorPrimaries_ITU_R_2020; 445cabdff1aSopenharmony_ci#endif 446cabdff1aSopenharmony_ci return CFSTR("ITU_R_2020"); 447cabdff1aSopenharmony_ci case AVCOL_PRI_BT709: 448cabdff1aSopenharmony_ci return kCVImageBufferColorPrimaries_ITU_R_709_2; 449cabdff1aSopenharmony_ci case AVCOL_PRI_SMPTE170M: 450cabdff1aSopenharmony_ci return kCVImageBufferColorPrimaries_SMPTE_C; 451cabdff1aSopenharmony_ci case AVCOL_PRI_BT470BG: 452cabdff1aSopenharmony_ci return kCVImageBufferColorPrimaries_EBU_3213; 453cabdff1aSopenharmony_ci default: 454cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG 455cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) 456cabdff1aSopenharmony_ci return CVColorPrimariesGetStringForIntegerCodePoint(pri); 457cabdff1aSopenharmony_ci#endif 458cabdff1aSopenharmony_ci case AVCOL_PRI_UNSPECIFIED: 459cabdff1aSopenharmony_ci return NULL; 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci} 462cabdff1aSopenharmony_ci 463cabdff1aSopenharmony_ciCFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc) 464cabdff1aSopenharmony_ci{ 465cabdff1aSopenharmony_ci 466cabdff1aSopenharmony_ci switch (trc) { 467cabdff1aSopenharmony_ci case AVCOL_TRC_SMPTE2084: 468cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ 469cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.13, iOS 11, *)) 470cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; 471cabdff1aSopenharmony_ci#endif 472cabdff1aSopenharmony_ci return CFSTR("SMPTE_ST_2084_PQ"); 473cabdff1aSopenharmony_ci case AVCOL_TRC_BT2020_10: 474cabdff1aSopenharmony_ci case AVCOL_TRC_BT2020_12: 475cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020 476cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.11, iOS 9, *)) 477cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_ITU_R_2020; 478cabdff1aSopenharmony_ci#endif 479cabdff1aSopenharmony_ci return CFSTR("ITU_R_2020"); 480cabdff1aSopenharmony_ci case AVCOL_TRC_BT709: 481cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_ITU_R_709_2; 482cabdff1aSopenharmony_ci case AVCOL_TRC_SMPTE240M: 483cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_SMPTE_240M_1995; 484cabdff1aSopenharmony_ci case AVCOL_TRC_SMPTE428: 485cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1 486cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.12, iOS 10, *)) 487cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_SMPTE_ST_428_1; 488cabdff1aSopenharmony_ci#endif 489cabdff1aSopenharmony_ci return CFSTR("SMPTE_ST_428_1"); 490cabdff1aSopenharmony_ci case AVCOL_TRC_ARIB_STD_B67: 491cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG 492cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.13, iOS 11, *)) 493cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_ITU_R_2100_HLG; 494cabdff1aSopenharmony_ci#endif 495cabdff1aSopenharmony_ci return CFSTR("ITU_R_2100_HLG"); 496cabdff1aSopenharmony_ci case AVCOL_TRC_GAMMA22: 497cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_UseGamma; 498cabdff1aSopenharmony_ci case AVCOL_TRC_GAMMA28: 499cabdff1aSopenharmony_ci return kCVImageBufferTransferFunction_UseGamma; 500cabdff1aSopenharmony_ci default: 501cabdff1aSopenharmony_ci#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG 502cabdff1aSopenharmony_ci if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) 503cabdff1aSopenharmony_ci return CVTransferFunctionGetStringForIntegerCodePoint(trc); 504cabdff1aSopenharmony_ci#endif 505cabdff1aSopenharmony_ci case AVCOL_TRC_UNSPECIFIED: 506cabdff1aSopenharmony_ci return NULL; 507cabdff1aSopenharmony_ci } 508cabdff1aSopenharmony_ci} 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_cistatic int vt_pixbuf_set_colorspace(void *log_ctx, 511cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf, const AVFrame *src) 512cabdff1aSopenharmony_ci{ 513cabdff1aSopenharmony_ci CFStringRef colormatrix = NULL, colorpri = NULL, colortrc = NULL; 514cabdff1aSopenharmony_ci Float32 gamma = 0; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci colormatrix = av_map_videotoolbox_color_matrix_from_av(src->colorspace); 517cabdff1aSopenharmony_ci if (!colormatrix && src->colorspace != AVCOL_SPC_UNSPECIFIED) 518cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_ci colorpri = av_map_videotoolbox_color_primaries_from_av(src->color_primaries); 521cabdff1aSopenharmony_ci if (!colorpri && src->color_primaries != AVCOL_PRI_UNSPECIFIED) 522cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); 523cabdff1aSopenharmony_ci 524cabdff1aSopenharmony_ci colortrc = av_map_videotoolbox_color_trc_from_av(src->color_trc); 525cabdff1aSopenharmony_ci if (!colortrc && src->color_trc != AVCOL_TRC_UNSPECIFIED) 526cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci if (src->color_trc == AVCOL_TRC_GAMMA22) 529cabdff1aSopenharmony_ci gamma = 2.2; 530cabdff1aSopenharmony_ci else if (src->color_trc == AVCOL_TRC_GAMMA28) 531cabdff1aSopenharmony_ci gamma = 2.8; 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci if (colormatrix) { 534cabdff1aSopenharmony_ci CVBufferSetAttachment( 535cabdff1aSopenharmony_ci pixbuf, 536cabdff1aSopenharmony_ci kCVImageBufferYCbCrMatrixKey, 537cabdff1aSopenharmony_ci colormatrix, 538cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate); 539cabdff1aSopenharmony_ci } 540cabdff1aSopenharmony_ci if (colorpri) { 541cabdff1aSopenharmony_ci CVBufferSetAttachment( 542cabdff1aSopenharmony_ci pixbuf, 543cabdff1aSopenharmony_ci kCVImageBufferColorPrimariesKey, 544cabdff1aSopenharmony_ci colorpri, 545cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate); 546cabdff1aSopenharmony_ci } 547cabdff1aSopenharmony_ci if (colortrc) { 548cabdff1aSopenharmony_ci CVBufferSetAttachment( 549cabdff1aSopenharmony_ci pixbuf, 550cabdff1aSopenharmony_ci kCVImageBufferTransferFunctionKey, 551cabdff1aSopenharmony_ci colortrc, 552cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate); 553cabdff1aSopenharmony_ci } 554cabdff1aSopenharmony_ci if (gamma != 0) { 555cabdff1aSopenharmony_ci CFNumberRef gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); 556cabdff1aSopenharmony_ci CVBufferSetAttachment( 557cabdff1aSopenharmony_ci pixbuf, 558cabdff1aSopenharmony_ci kCVImageBufferGammaLevelKey, 559cabdff1aSopenharmony_ci gamma_level, 560cabdff1aSopenharmony_ci kCVAttachmentMode_ShouldPropagate); 561cabdff1aSopenharmony_ci CFRelease(gamma_level); 562cabdff1aSopenharmony_ci } 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci return 0; 565cabdff1aSopenharmony_ci} 566cabdff1aSopenharmony_ci 567cabdff1aSopenharmony_cistatic int vt_pixbuf_set_attachments(void *log_ctx, 568cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf, const AVFrame *src) 569cabdff1aSopenharmony_ci{ 570cabdff1aSopenharmony_ci int ret; 571cabdff1aSopenharmony_ci ret = vt_pixbuf_set_par(log_ctx, pixbuf, src); 572cabdff1aSopenharmony_ci if (ret < 0) 573cabdff1aSopenharmony_ci return ret; 574cabdff1aSopenharmony_ci ret = vt_pixbuf_set_colorspace(log_ctx, pixbuf, src); 575cabdff1aSopenharmony_ci if (ret < 0) 576cabdff1aSopenharmony_ci return ret; 577cabdff1aSopenharmony_ci ret = vt_pixbuf_set_chromaloc(log_ctx, pixbuf, src); 578cabdff1aSopenharmony_ci if (ret < 0) 579cabdff1aSopenharmony_ci return ret; 580cabdff1aSopenharmony_ci return 0; 581cabdff1aSopenharmony_ci} 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ciint av_vt_pixbuf_set_attachments(void *log_ctx, 584cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf, const AVFrame *src) 585cabdff1aSopenharmony_ci{ 586cabdff1aSopenharmony_ci return vt_pixbuf_set_attachments(log_ctx, pixbuf, src); 587cabdff1aSopenharmony_ci} 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_cistatic int vt_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, 590cabdff1aSopenharmony_ci int flags) 591cabdff1aSopenharmony_ci{ 592cabdff1aSopenharmony_ci CVPixelBufferRef pixbuf = (CVPixelBufferRef)src->data[3]; 593cabdff1aSopenharmony_ci OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); 594cabdff1aSopenharmony_ci CVReturn err; 595cabdff1aSopenharmony_ci uint32_t map_flags = 0; 596cabdff1aSopenharmony_ci int ret; 597cabdff1aSopenharmony_ci int i; 598cabdff1aSopenharmony_ci enum AVPixelFormat format; 599cabdff1aSopenharmony_ci 600cabdff1aSopenharmony_ci format = av_map_videotoolbox_format_to_pixfmt(pixel_format); 601cabdff1aSopenharmony_ci if (dst->format != format) { 602cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Unsupported or mismatching pixel format: %s\n", 603cabdff1aSopenharmony_ci av_fourcc2str(pixel_format)); 604cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 605cabdff1aSopenharmony_ci } 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci if (CVPixelBufferGetWidth(pixbuf) != ctx->width || 608cabdff1aSopenharmony_ci CVPixelBufferGetHeight(pixbuf) != ctx->height) { 609cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Inconsistent frame dimensions.\n"); 610cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 611cabdff1aSopenharmony_ci } 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci if (flags == AV_HWFRAME_MAP_READ) 614cabdff1aSopenharmony_ci map_flags = kCVPixelBufferLock_ReadOnly; 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_ci err = CVPixelBufferLockBaseAddress(pixbuf, map_flags); 617cabdff1aSopenharmony_ci if (err != kCVReturnSuccess) { 618cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); 619cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 620cabdff1aSopenharmony_ci } 621cabdff1aSopenharmony_ci 622cabdff1aSopenharmony_ci if (CVPixelBufferIsPlanar(pixbuf)) { 623cabdff1aSopenharmony_ci int planes = CVPixelBufferGetPlaneCount(pixbuf); 624cabdff1aSopenharmony_ci for (i = 0; i < planes; i++) { 625cabdff1aSopenharmony_ci dst->data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); 626cabdff1aSopenharmony_ci dst->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); 627cabdff1aSopenharmony_ci } 628cabdff1aSopenharmony_ci } else { 629cabdff1aSopenharmony_ci dst->data[0] = CVPixelBufferGetBaseAddress(pixbuf); 630cabdff1aSopenharmony_ci dst->linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); 631cabdff1aSopenharmony_ci } 632cabdff1aSopenharmony_ci 633cabdff1aSopenharmony_ci ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, vt_unmap, 634cabdff1aSopenharmony_ci (void *)(uintptr_t)map_flags); 635cabdff1aSopenharmony_ci if (ret < 0) 636cabdff1aSopenharmony_ci goto unlock; 637cabdff1aSopenharmony_ci 638cabdff1aSopenharmony_ci return 0; 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ciunlock: 641cabdff1aSopenharmony_ci CVPixelBufferUnlockBaseAddress(pixbuf, map_flags); 642cabdff1aSopenharmony_ci return ret; 643cabdff1aSopenharmony_ci} 644cabdff1aSopenharmony_ci 645cabdff1aSopenharmony_cistatic int vt_transfer_data_from(AVHWFramesContext *hwfc, 646cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src) 647cabdff1aSopenharmony_ci{ 648cabdff1aSopenharmony_ci AVFrame *map; 649cabdff1aSopenharmony_ci int err; 650cabdff1aSopenharmony_ci 651cabdff1aSopenharmony_ci if (dst->width > hwfc->width || dst->height > hwfc->height) 652cabdff1aSopenharmony_ci return AVERROR(EINVAL); 653cabdff1aSopenharmony_ci 654cabdff1aSopenharmony_ci map = av_frame_alloc(); 655cabdff1aSopenharmony_ci if (!map) 656cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 657cabdff1aSopenharmony_ci map->format = dst->format; 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci err = vt_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ); 660cabdff1aSopenharmony_ci if (err) 661cabdff1aSopenharmony_ci goto fail; 662cabdff1aSopenharmony_ci 663cabdff1aSopenharmony_ci map->width = dst->width; 664cabdff1aSopenharmony_ci map->height = dst->height; 665cabdff1aSopenharmony_ci 666cabdff1aSopenharmony_ci err = av_frame_copy(dst, map); 667cabdff1aSopenharmony_ci if (err) 668cabdff1aSopenharmony_ci goto fail; 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci err = 0; 671cabdff1aSopenharmony_cifail: 672cabdff1aSopenharmony_ci av_frame_free(&map); 673cabdff1aSopenharmony_ci return err; 674cabdff1aSopenharmony_ci} 675cabdff1aSopenharmony_ci 676cabdff1aSopenharmony_cistatic int vt_transfer_data_to(AVHWFramesContext *hwfc, 677cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src) 678cabdff1aSopenharmony_ci{ 679cabdff1aSopenharmony_ci AVFrame *map; 680cabdff1aSopenharmony_ci int err; 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci if (src->width > hwfc->width || src->height > hwfc->height) 683cabdff1aSopenharmony_ci return AVERROR(EINVAL); 684cabdff1aSopenharmony_ci 685cabdff1aSopenharmony_ci map = av_frame_alloc(); 686cabdff1aSopenharmony_ci if (!map) 687cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 688cabdff1aSopenharmony_ci map->format = src->format; 689cabdff1aSopenharmony_ci 690cabdff1aSopenharmony_ci err = vt_map_frame(hwfc, map, dst, AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE); 691cabdff1aSopenharmony_ci if (err) 692cabdff1aSopenharmony_ci goto fail; 693cabdff1aSopenharmony_ci 694cabdff1aSopenharmony_ci map->width = src->width; 695cabdff1aSopenharmony_ci map->height = src->height; 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_ci err = av_frame_copy(map, src); 698cabdff1aSopenharmony_ci if (err) 699cabdff1aSopenharmony_ci goto fail; 700cabdff1aSopenharmony_ci 701cabdff1aSopenharmony_ci err = vt_pixbuf_set_attachments(hwfc, (CVPixelBufferRef)dst->data[3], src); 702cabdff1aSopenharmony_ci if (err) 703cabdff1aSopenharmony_ci goto fail; 704cabdff1aSopenharmony_ci 705cabdff1aSopenharmony_ci err = 0; 706cabdff1aSopenharmony_cifail: 707cabdff1aSopenharmony_ci av_frame_free(&map); 708cabdff1aSopenharmony_ci return err; 709cabdff1aSopenharmony_ci} 710cabdff1aSopenharmony_ci 711cabdff1aSopenharmony_cistatic int vt_map_from(AVHWFramesContext *hwfc, AVFrame *dst, 712cabdff1aSopenharmony_ci const AVFrame *src, int flags) 713cabdff1aSopenharmony_ci{ 714cabdff1aSopenharmony_ci int err; 715cabdff1aSopenharmony_ci 716cabdff1aSopenharmony_ci if (dst->format == AV_PIX_FMT_NONE) 717cabdff1aSopenharmony_ci dst->format = hwfc->sw_format; 718cabdff1aSopenharmony_ci else if (dst->format != hwfc->sw_format) 719cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 720cabdff1aSopenharmony_ci 721cabdff1aSopenharmony_ci err = vt_map_frame(hwfc, dst, src, flags); 722cabdff1aSopenharmony_ci if (err) 723cabdff1aSopenharmony_ci return err; 724cabdff1aSopenharmony_ci 725cabdff1aSopenharmony_ci dst->width = src->width; 726cabdff1aSopenharmony_ci dst->height = src->height; 727cabdff1aSopenharmony_ci 728cabdff1aSopenharmony_ci err = av_frame_copy_props(dst, src); 729cabdff1aSopenharmony_ci if (err) 730cabdff1aSopenharmony_ci return err; 731cabdff1aSopenharmony_ci 732cabdff1aSopenharmony_ci return 0; 733cabdff1aSopenharmony_ci} 734cabdff1aSopenharmony_ci 735cabdff1aSopenharmony_cistatic int vt_device_create(AVHWDeviceContext *ctx, const char *device, 736cabdff1aSopenharmony_ci AVDictionary *opts, int flags) 737cabdff1aSopenharmony_ci{ 738cabdff1aSopenharmony_ci if (device && device[0]) { 739cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n"); 740cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 741cabdff1aSopenharmony_ci } 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_ci return 0; 744cabdff1aSopenharmony_ci} 745cabdff1aSopenharmony_ci 746cabdff1aSopenharmony_ciconst HWContextType ff_hwcontext_type_videotoolbox = { 747cabdff1aSopenharmony_ci .type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX, 748cabdff1aSopenharmony_ci .name = "videotoolbox", 749cabdff1aSopenharmony_ci 750cabdff1aSopenharmony_ci .frames_priv_size = sizeof(VTFramesContext), 751cabdff1aSopenharmony_ci 752cabdff1aSopenharmony_ci .device_create = vt_device_create, 753cabdff1aSopenharmony_ci .frames_init = vt_frames_init, 754cabdff1aSopenharmony_ci .frames_get_buffer = vt_get_buffer, 755cabdff1aSopenharmony_ci .frames_get_constraints = vt_frames_get_constraints, 756cabdff1aSopenharmony_ci .frames_uninit = vt_frames_uninit, 757cabdff1aSopenharmony_ci .transfer_get_formats = vt_transfer_get_formats, 758cabdff1aSopenharmony_ci .transfer_data_to = vt_transfer_data_to, 759cabdff1aSopenharmony_ci .transfer_data_from = vt_transfer_data_from, 760cabdff1aSopenharmony_ci .map_from = vt_map_from, 761cabdff1aSopenharmony_ci 762cabdff1aSopenharmony_ci .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE }, 763cabdff1aSopenharmony_ci}; 764