FFmpeg
Loading...
Searching...
No Matches
hwcontext_videotoolbox.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "config.h"
20
21#include <stdint.h>
22#include <string.h>
23
24#include <VideoToolbox/VideoToolbox.h>
25
26#include "buffer.h"
27#include "buffer_internal.h"
28#include "common.h"
29#include "hwcontext.h"
30#include "hwcontext_internal.h"
32#include "attributes.h"
33#include "mem.h"
34#include "pixfmt.h"
35#include "pixdesc.h"
36
37typedef struct VTFramesContext {
38 /**
39 * The public AVVTFramesContext. See hwcontext_videotoolbox.h for it.
40 */
42 CVPixelBufferPoolRef pool;
44
45static const struct {
46 uint32_t cv_fmt;
49} cv_pix_fmts[] = {
50 { kCVPixelFormatType_420YpCbCr8Planar, false, AV_PIX_FMT_YUV420P },
51 { kCVPixelFormatType_420YpCbCr8PlanarFullRange, true, AV_PIX_FMT_YUV420P },
52 { kCVPixelFormatType_422YpCbCr8, false, AV_PIX_FMT_UYVY422 },
53 { kCVPixelFormatType_32BGRA, true, AV_PIX_FMT_BGRA },
54#ifdef kCFCoreFoundationVersionNumber10_7
55 { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV12 },
56 { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV12 },
57 { kCVPixelFormatType_4444AYpCbCr8, false, AV_PIX_FMT_AYUV },
58 { kCVPixelFormatType_4444AYpCbCr16, false, AV_PIX_FMT_AYUV64 },
59#endif
60#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
63#endif
64#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
65 { kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV16 },
66 { kCVPixelFormatType_422YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV16 },
67#endif
68#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
69 { kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P210 },
70 { kCVPixelFormatType_422YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P210 },
71#endif
72#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
73 { kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P216 },
74#endif
75#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
76 { kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV24 },
77 { kCVPixelFormatType_444YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV24 },
78#endif
79#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
80 { kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P410 },
81 { kCVPixelFormatType_444YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P410 },
82#endif
83#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
84 { kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P416 },
85#endif
86#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8_YUVS
87 { kCVPixelFormatType_422YpCbCr8_yuvs, false, AV_PIX_FMT_YUYV422 },
88#endif
89 { 'bp16'/*kCVPixelFormatType_16VersatileBayer*/, false, AV_PIX_FMT_BAYER_RGGB16},
90};
91
92static const enum AVPixelFormat supported_formats[] = {
93#ifdef kCFCoreFoundationVersionNumber10_7
97#endif
100#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
102#endif
103#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
105#endif
106#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
108#endif
109#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
111#endif
112#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
114#endif
115#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
117#endif
118#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
120#endif
121#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8_YUVS
123#endif
126};
127
129 const void *hwconfig,
130 AVHWFramesConstraints *constraints)
131{
132 int i;
133
135 sizeof(*constraints->valid_sw_formats));
136 if (!constraints->valid_sw_formats)
137 return AVERROR(ENOMEM);
138
139 for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
140 constraints->valid_sw_formats[i] = supported_formats[i];
142
143 constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
144 if (!constraints->valid_hw_formats)
145 return AVERROR(ENOMEM);
146
148 constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
149
150 return 0;
151}
152
154{
155 int i;
156 for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
157 if (cv_pix_fmts[i].cv_fmt == cv_fmt)
158 return cv_pix_fmts[i].pix_fmt;
159 }
160 return AV_PIX_FMT_NONE;
161}
162
164 enum AVColorRange range)
165{
166 for (int i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
167 if (cv_pix_fmts[i].pix_fmt == pix_fmt) {
169
170 // Don't care if unspecified
172 return cv_pix_fmts[i].cv_fmt;
173
175 return cv_pix_fmts[i].cv_fmt;
176 }
177 }
178
179 return 0;
180}
181
186
191
193{
194 VTFramesContext *fctx = ctx->hwctx;
195 AVVTFramesContext *hw_ctx = &fctx->p;
196 CVReturn err;
197 CFNumberRef w, h, pixfmt;
198 uint32_t cv_pixfmt;
199 CFMutableDictionaryRef attributes, iosurface_properties;
200
201 attributes = CFDictionaryCreateMutable(
202 NULL,
203 2,
204 &kCFTypeDictionaryKeyCallBacks,
205 &kCFTypeDictionaryValueCallBacks);
206
207 cv_pixfmt = vt_format_from_pixfmt(ctx->sw_format, hw_ctx->color_range);
208 pixfmt = CFNumberCreate(NULL, kCFNumberSInt32Type, &cv_pixfmt);
209 CFDictionarySetValue(
210 attributes,
211 kCVPixelBufferPixelFormatTypeKey,
212 pixfmt);
213 CFRelease(pixfmt);
214
215 iosurface_properties = CFDictionaryCreateMutable(
216 NULL,
217 0,
218 &kCFTypeDictionaryKeyCallBacks,
219 &kCFTypeDictionaryValueCallBacks);
220 CFDictionarySetValue(attributes, kCVPixelBufferIOSurfacePropertiesKey, iosurface_properties);
221 CFRelease(iosurface_properties);
222
223 w = CFNumberCreate(NULL, kCFNumberSInt32Type, &ctx->width);
224 h = CFNumberCreate(NULL, kCFNumberSInt32Type, &ctx->height);
225 CFDictionarySetValue(attributes, kCVPixelBufferWidthKey, w);
226 CFDictionarySetValue(attributes, kCVPixelBufferHeightKey, h);
227 CFRelease(w);
228 CFRelease(h);
229
230 err = CVPixelBufferPoolCreate(
231 NULL,
232 NULL,
233 attributes,
234 &fctx->pool);
235 CFRelease(attributes);
236
237 if (err == kCVReturnSuccess)
238 return 0;
239
240 av_log(ctx, AV_LOG_ERROR, "Error creating CVPixelBufferPool: %d\n", err);
241 return AVERROR_EXTERNAL;
242}
243
244static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
245{
246 CVPixelBufferRelease((CVPixelBufferRef)data);
247}
248
249static AVBufferRef *vt_pool_alloc_buffer(void *opaque, size_t size)
250{
251 CVPixelBufferRef pixbuf;
252 AVBufferRef *buf;
253 CVReturn err;
254 AVHWFramesContext *ctx = opaque;
255 VTFramesContext *fctx = ctx->hwctx;
256
257 err = CVPixelBufferPoolCreatePixelBuffer(
258 NULL,
259 fctx->pool,
260 &pixbuf
261 );
262 if (err != kCVReturnSuccess) {
263 av_log(ctx, AV_LOG_ERROR, "Failed to create pixel buffer from pool: %d\n", err);
264 return NULL;
265 }
266
267 buf = av_buffer_create((uint8_t *)pixbuf, size,
269 if (!buf) {
270 CVPixelBufferRelease(pixbuf);
271 return NULL;
272 }
273 return buf;
274}
275
277{
278 VTFramesContext *fctx = ctx->hwctx;
279 if (fctx->pool) {
280 CVPixelBufferPoolRelease(fctx->pool);
281 fctx->pool = NULL;
282 }
283}
284
286{
287 int i, ret;
288
289 for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
290 if (ctx->sw_format == supported_formats[i])
291 break;
292 }
294 av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
295 av_get_pix_fmt_name(ctx->sw_format));
296 return AVERROR(ENOSYS);
297 }
298
299 if (!ctx->pool) {
301 sizeof(CVPixelBufferRef), ctx, vt_pool_alloc_buffer, NULL);
302 if (!ffhwframesctx(ctx)->pool_internal)
303 return AVERROR(ENOMEM);
304 }
305
306 ret = vt_pool_alloc(ctx);
307 if (ret < 0)
308 return ret;
309
310 return 0;
311}
312
314{
315 frame->buf[0] = av_buffer_pool_get(ctx->pool);
316 if (!frame->buf[0])
317 return AVERROR(ENOMEM);
318
319 frame->data[3] = frame->buf[0]->data;
321 frame->width = ctx->width;
322 frame->height = ctx->height;
323
324 return 0;
325}
326
329 enum AVPixelFormat **formats)
330{
331 enum AVPixelFormat *fmts = av_malloc_array(2, sizeof(*fmts));
332 if (!fmts)
333 return AVERROR(ENOMEM);
334
335 fmts[0] = ctx->sw_format;
336 fmts[1] = AV_PIX_FMT_NONE;
337
338 *formats = fmts;
339 return 0;
340}
341
343{
344 CVPixelBufferRef pixbuf = (CVPixelBufferRef)hwmap->source->data[3];
345
346 CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv);
347}
348
349static int vt_pixbuf_set_par(void *log_ctx,
350 CVPixelBufferRef pixbuf, const AVFrame *src)
351{
352 CFMutableDictionaryRef par = NULL;
353 CFNumberRef num = NULL, den = NULL;
354 AVRational avpar = src->sample_aspect_ratio;
355
356 if (avpar.num == 0) {
357 CVBufferRemoveAttachment(pixbuf, kCVImageBufferPixelAspectRatioKey);
358 return 0;
359 }
360
361 av_reduce(&avpar.num, &avpar.den,
362 avpar.num, avpar.den,
363 0xFFFFFFFF);
364
365 num = CFNumberCreate(kCFAllocatorDefault,
366 kCFNumberIntType,
367 &avpar.num);
368
369 den = CFNumberCreate(kCFAllocatorDefault,
370 kCFNumberIntType,
371 &avpar.den);
372
373 par = CFDictionaryCreateMutable(kCFAllocatorDefault,
374 2,
375 &kCFCopyStringDictionaryKeyCallBacks,
376 &kCFTypeDictionaryValueCallBacks);
377
378 if (!par || !num || !den) {
379 if (par) CFRelease(par);
380 if (num) CFRelease(num);
381 if (den) CFRelease(den);
382 return AVERROR(ENOMEM);
383 }
384
385 CFDictionarySetValue(
386 par,
387 kCVImageBufferPixelAspectRatioHorizontalSpacingKey,
388 num);
389 CFDictionarySetValue(
390 par,
391 kCVImageBufferPixelAspectRatioVerticalSpacingKey,
392 den);
393
394 CVBufferSetAttachment(
395 pixbuf,
396 kCVImageBufferPixelAspectRatioKey,
397 par,
398 kCVAttachmentMode_ShouldPropagate
399 );
400
401 CFRelease(par);
402 CFRelease(num);
403 CFRelease(den);
404
405 return 0;
406}
407
409{
410 switch (loc) {
412 return kCVImageBufferChromaLocation_Left;
414 return kCVImageBufferChromaLocation_Center;
415 case AVCHROMA_LOC_TOP:
416 return kCVImageBufferChromaLocation_Top;
418 return kCVImageBufferChromaLocation_Bottom;
420 return kCVImageBufferChromaLocation_TopLeft;
422 return kCVImageBufferChromaLocation_BottomLeft;
423 default:
424 return NULL;
425 }
426}
427
428static int vt_pixbuf_set_chromaloc(void *log_ctx,
429 CVPixelBufferRef pixbuf, const AVFrame *src)
430{
431 CFStringRef loc = av_map_videotoolbox_chroma_loc_from_av(src->chroma_location);
432
433 if (loc) {
434 CVBufferSetAttachment(
435 pixbuf,
436 kCVImageBufferChromaLocationTopFieldKey,
437 loc,
438 kCVAttachmentMode_ShouldPropagate);
439 } else
440 CVBufferRemoveAttachment(
441 pixbuf,
442 kCVImageBufferChromaLocationTopFieldKey);
443
444 return 0;
445}
446
448{
449 switch (space) {
452#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020
453 if (__builtin_available(macOS 10.11, iOS 9, *))
455#endif
456 return CFSTR("ITU_R_2020");
459 return kCVImageBufferYCbCrMatrix_ITU_R_601_4;
460 case AVCOL_SPC_BT709:
461 return kCVImageBufferYCbCrMatrix_ITU_R_709_2;
463 return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
464 default:
465#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG
466 if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *))
467 return CVYCbCrMatrixGetStringForIntegerCodePoint(space);
469#endif
471 return NULL;
472 }
473}
474
476{
477 switch (pri) {
478 case AVCOL_PRI_BT2020:
479#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020
480 if (__builtin_available(macOS 10.11, iOS 9, *))
482#endif
483 return CFSTR("ITU_R_2020");
484 case AVCOL_PRI_BT709:
485 return kCVImageBufferColorPrimaries_ITU_R_709_2;
487 return kCVImageBufferColorPrimaries_SMPTE_C;
489 return kCVImageBufferColorPrimaries_EBU_3213;
490 default:
491#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG
492 if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *))
493 return CVColorPrimariesGetStringForIntegerCodePoint(pri);
495#endif
497 return NULL;
498 }
499}
500
502{
503
504 switch (trc) {
506#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ
507 if (__builtin_available(macOS 10.13, iOS 11, *))
508 return kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ;
509#endif
510 return CFSTR("SMPTE_ST_2084_PQ");
513#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020
514 if (__builtin_available(macOS 10.11, iOS 9, *))
516#endif
517 return CFSTR("ITU_R_2020");
518 case AVCOL_TRC_BT709:
519 return kCVImageBufferTransferFunction_ITU_R_709_2;
521 return kCVImageBufferTransferFunction_SMPTE_240M_1995;
523#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1
524 if (__builtin_available(macOS 10.12, iOS 10, *))
525 return kCVImageBufferTransferFunction_SMPTE_ST_428_1;
526#endif
527 return CFSTR("SMPTE_ST_428_1");
529#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG
530 if (__builtin_available(macOS 10.13, iOS 11, *))
531 return kCVImageBufferTransferFunction_ITU_R_2100_HLG;
532#endif
533 return CFSTR("ITU_R_2100_HLG");
535 return kCVImageBufferTransferFunction_UseGamma;
537 return kCVImageBufferTransferFunction_UseGamma;
538 default:
539#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG
540 if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *))
541 return CVTransferFunctionGetStringForIntegerCodePoint(trc);
543#endif
545 return NULL;
546 }
547}
548
549/**
550 * Copy all attachments for the specified mode from the given buffer.
551 */
552static CFDictionaryRef vt_cv_buffer_copy_attachments(CVBufferRef buffer,
553 CVAttachmentMode attachment_mode)
554{
555 // Check that our SDK is at least macOS 12 / iOS 15 / tvOS 15
556 #if (TARGET_OS_OSX && defined(__MAC_12_0) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0) || \
557 (TARGET_OS_IOS && defined(__IPHONE_15_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_0) || \
558 (TARGET_OS_TV && defined(__TVOS_15_0) && __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_15_0)
559 // On recent enough versions, just use the respective API
560 if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, *))
561 return CVBufferCopyAttachments(buffer, attachment_mode);
562 #endif
563
564 // Check that the target is lower than macOS 12 / iOS 15 / tvOS 15
565 // else this would generate a deprecation warning and anyway never run because
566 // the runtime availability check above would be always true.
567 #if (TARGET_OS_OSX && (!defined(__MAC_12_0) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_12_0)) || \
568 (TARGET_OS_IOS && (!defined(__IPHONE_15_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_15_0)) || \
569 (TARGET_OS_TV && (!defined(__TVOS_15_0) || __TV_OS_VERSION_MIN_REQUIRED < __TVOS_15_0))
570 // Fallback on SDKs or runtime versions < macOS 12 / iOS 15 / tvOS 15
571 CFDictionaryRef dict = CVBufferGetAttachments(buffer, attachment_mode);
572 return (dict) ? CFDictionaryCreateCopy(NULL, dict) : NULL;
573 #else
574 return NULL; // Impossible, just make the compiler happy
575 #endif
576}
577
578static int vt_pixbuf_set_colorspace(void *log_ctx,
579 CVPixelBufferRef pixbuf, const AVFrame *src)
580{
581 CGColorSpaceRef colorspace = NULL;
582 CFStringRef colormatrix = NULL, colorpri = NULL, colortrc = NULL;
583 Float32 gamma = 0;
584
585 colormatrix = av_map_videotoolbox_color_matrix_from_av(src->colorspace);
586 if (colormatrix)
587 CVBufferSetAttachment(pixbuf, kCVImageBufferYCbCrMatrixKey,
588 colormatrix, kCVAttachmentMode_ShouldPropagate);
589 else {
590 CVBufferRemoveAttachment(pixbuf, kCVImageBufferYCbCrMatrixKey);
591 if (src->colorspace != AVCOL_SPC_UNSPECIFIED && src->colorspace != AVCOL_SPC_RGB)
592 av_log(log_ctx, AV_LOG_WARNING,
593 "Color space %s is not supported.\n",
594 av_color_space_name(src->colorspace));
595 }
596
597 colorpri = av_map_videotoolbox_color_primaries_from_av(src->color_primaries);
598 if (colorpri)
599 CVBufferSetAttachment(pixbuf, kCVImageBufferColorPrimariesKey,
600 colorpri, kCVAttachmentMode_ShouldPropagate);
601 else {
602 CVBufferRemoveAttachment(pixbuf, kCVImageBufferColorPrimariesKey);
603 if (src->color_primaries != AVCOL_PRI_UNSPECIFIED)
604 av_log(log_ctx, AV_LOG_WARNING,
605 "Color primaries %s is not supported.\n",
606 av_color_primaries_name(src->color_primaries));
607 }
608
609 colortrc = av_map_videotoolbox_color_trc_from_av(src->color_trc);
610 if (colortrc)
611 CVBufferSetAttachment(pixbuf, kCVImageBufferTransferFunctionKey,
612 colortrc, kCVAttachmentMode_ShouldPropagate);
613 else {
614 CVBufferRemoveAttachment(pixbuf, kCVImageBufferTransferFunctionKey);
615 if (src->color_trc != AVCOL_TRC_UNSPECIFIED)
616 av_log(log_ctx, AV_LOG_WARNING,
617 "Color transfer function %s is not supported.\n",
618 av_color_transfer_name(src->color_trc));
619 }
620
621 if (src->color_trc == AVCOL_TRC_GAMMA22)
622 gamma = 2.2;
623 else if (src->color_trc == AVCOL_TRC_GAMMA28)
624 gamma = 2.8;
625
626 if (gamma != 0) {
627 CFNumberRef gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
628 CVBufferSetAttachment(pixbuf, kCVImageBufferGammaLevelKey,
629 gamma_level, kCVAttachmentMode_ShouldPropagate);
630 CFRelease(gamma_level);
631 } else
632 CVBufferRemoveAttachment(pixbuf, kCVImageBufferGammaLevelKey);
633
634#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MAX_ALLOWED >= 100800) || \
635 (TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000)
636 if (__builtin_available(macOS 10.8, iOS 10, *)) {
637 CFDictionaryRef attachments =
638 vt_cv_buffer_copy_attachments(pixbuf, kCVAttachmentMode_ShouldPropagate);
639
640 if (attachments) {
641 colorspace =
642 CVImageBufferCreateColorSpaceFromAttachments(attachments);
643 CFRelease(attachments);
644 }
645 }
646#endif
647
648 // Done outside the above preprocessor code and if's so that
649 // in any case a wrong kCVImageBufferCGColorSpaceKey is removed
650 // if the above code is not used or fails.
651 if (colorspace) {
652 CVBufferSetAttachment(pixbuf, kCVImageBufferCGColorSpaceKey,
653 colorspace, kCVAttachmentMode_ShouldPropagate);
654 CFRelease(colorspace);
655 } else
656 CVBufferRemoveAttachment(pixbuf, kCVImageBufferCGColorSpaceKey);
657
658 return 0;
659}
660
661static int vt_pixbuf_set_attachments(void *log_ctx,
662 CVPixelBufferRef pixbuf, const AVFrame *src)
663{
664 int ret;
665 ret = vt_pixbuf_set_par(log_ctx, pixbuf, src);
666 if (ret < 0)
667 return ret;
668 ret = vt_pixbuf_set_colorspace(log_ctx, pixbuf, src);
669 if (ret < 0)
670 return ret;
671 ret = vt_pixbuf_set_chromaloc(log_ctx, pixbuf, src);
672 if (ret < 0)
673 return ret;
674 return 0;
675}
676
678 CVPixelBufferRef pixbuf, const AVFrame *src)
679{
680 return vt_pixbuf_set_attachments(log_ctx, pixbuf, src);
681}
682
684 int flags)
685{
686 CVPixelBufferRef pixbuf = (CVPixelBufferRef)src->data[3];
687 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
688 CVReturn err;
689 uint32_t map_flags = 0;
690 int ret;
691 int i;
693
695 if (dst->format != format) {
696 av_log(ctx, AV_LOG_ERROR, "Unsupported or mismatching pixel format: %s\n",
697 av_fourcc2str(pixel_format));
698 return AVERROR_UNKNOWN;
699 }
700
701 if (CVPixelBufferGetWidth(pixbuf) != ctx->width ||
702 CVPixelBufferGetHeight(pixbuf) != ctx->height) {
703 av_log(ctx, AV_LOG_ERROR, "Inconsistent frame dimensions.\n");
704 return AVERROR_UNKNOWN;
705 }
706
708 map_flags = kCVPixelBufferLock_ReadOnly;
709
710 err = CVPixelBufferLockBaseAddress(pixbuf, map_flags);
711 if (err != kCVReturnSuccess) {
712 av_log(ctx, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
713 return AVERROR_UNKNOWN;
714 }
715
716 if (CVPixelBufferIsPlanar(pixbuf)) {
717 int planes = CVPixelBufferGetPlaneCount(pixbuf);
718 for (i = 0; i < planes; i++) {
719 dst->data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
720 dst->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
721 }
722 } else {
723 dst->data[0] = CVPixelBufferGetBaseAddress(pixbuf);
724 dst->linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
725 }
726
727 ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, vt_unmap,
728 (void *)(uintptr_t)map_flags);
729 if (ret < 0)
730 goto unlock;
731
732 return 0;
733
734unlock:
735 CVPixelBufferUnlockBaseAddress(pixbuf, map_flags);
736 return ret;
737}
738
740 AVFrame *dst, const AVFrame *src)
741{
742 AVFrame *map;
743 int err;
744
745 if (dst->width > hwfc->width || dst->height > hwfc->height)
746 return AVERROR(EINVAL);
747
749 if (!map)
750 return AVERROR(ENOMEM);
751 map->format = dst->format;
752
754 if (err)
755 goto fail;
756
757 map->width = dst->width;
758 map->height = dst->height;
759
760 err = av_frame_copy(dst, map);
761 if (err)
762 goto fail;
763
764 err = 0;
765fail:
767 return err;
768}
769
771 AVFrame *dst, const AVFrame *src)
772{
773 AVFrame *map;
774 int err;
775
776 if (src->width > hwfc->width || src->height > hwfc->height)
777 return AVERROR(EINVAL);
778
780 if (!map)
781 return AVERROR(ENOMEM);
782 map->format = src->format;
783
785 if (err)
786 goto fail;
787
788 map->width = src->width;
789 map->height = src->height;
790
791 err = av_frame_copy(map, src);
792 if (err)
793 goto fail;
794
795 err = vt_pixbuf_set_attachments(hwfc, (CVPixelBufferRef)dst->data[3], src);
796 if (err)
797 goto fail;
798
799 err = 0;
800fail:
802 return err;
803}
804
806 const AVFrame *src, int flags)
807{
808 int err;
809
810 if (dst->format == AV_PIX_FMT_NONE)
811 dst->format = hwfc->sw_format;
812 else if (dst->format != hwfc->sw_format)
813 return AVERROR(ENOSYS);
814
815 err = vt_map_frame(hwfc, dst, src, flags);
816 if (err)
817 return err;
818
819 dst->width = src->width;
820 dst->height = src->height;
821
823 if (err)
824 return err;
825
826 return 0;
827}
828
829static int vt_device_create(AVHWDeviceContext *ctx, const char *device,
830 AVDictionary *opts, int flags)
831{
832 if (device && device[0]) {
833 av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n");
834 return AVERROR_UNKNOWN;
835 }
836
837 return 0;
838}
839
842 .name = "videotoolbox",
843
844 .frames_hwctx_size = sizeof(VTFramesContext),
845
846 .device_create = vt_device_create,
847 .frames_init = vt_frames_init,
848 .frames_get_buffer = vt_get_buffer,
849 .frames_get_constraints = vt_frames_get_constraints,
850 .frames_uninit = vt_frames_uninit,
851 .transfer_get_formats = vt_transfer_get_formats,
852 .transfer_data_to = vt_transfer_data_to,
853 .transfer_data_from = vt_transfer_data_from,
854 .map_from = vt_map_from,
855
857};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static const char *const format[]
Definition af_aiir.c:444
refcounted data buffer API
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define NULL
Definition coverity.c:32
static enum AVPixelFormat pix_fmt
static AVFrame * frame
#define fail
Definition test.h:479
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition buffer.c:390
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition buffer.c:259
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition frame.c:711
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
#define av_fourcc2str(fourcc)
Definition avutil.h:323
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition hwcontext.c:741
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition hwcontext.h:515
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition hwcontext.h:519
@ AV_HWFRAME_MAP_OVERWRITE
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition hwcontext.h:525
AVHWFrameTransferDirection
Definition hwcontext.h:406
@ AV_HWDEVICE_TYPE_VIDEOTOOLBOX
Definition hwcontext.h:34
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_videotoolbox
const VDPAUPixFmtMap * map
static int vt_pixbuf_set_chromaloc(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
CFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc)
Convert an AVChromaLocation to a VideoToolbox/CoreVideo chroma location string.
static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
static int vt_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
int av_vt_pixbuf_set_attachments(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
static void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap)
static const struct @344211167133375235025150301172257371040060013302 cv_pix_fmts[]
static int vt_pixbuf_set_attachments(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
static int vt_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vt_pixbuf_set_par(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
static uint32_t vt_format_from_pixfmt(enum AVPixelFormat pix_fmt, enum AVColorRange range)
enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt)
Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat.
CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space)
Convert an AVColorSpace to a VideoToolbox/CoreVideo color matrix string.
static int vt_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vt_pixbuf_set_colorspace(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
static int vt_frames_init(AVHWFramesContext *ctx)
static int vt_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri)
Convert an AVColorPrimaries to a VideoToolbox/CoreVideo color primaries string.
uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt)
Convert an AVPixelFormat to a VideoToolbox (actually CoreVideo) format.
static AVBufferRef * vt_pool_alloc_buffer(void *opaque, size_t size)
static int vt_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
uint32_t cv_fmt
static int vt_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static CFDictionaryRef vt_cv_buffer_copy_attachments(CVBufferRef buffer, CVAttachmentMode attachment_mode)
Copy all attachments for the specified mode from the given buffer.
static void vt_frames_uninit(AVHWFramesContext *ctx)
uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range)
Same as av_map_videotoolbox_format_from_pixfmt function, but can map and return full range pixel form...
static int vt_pool_alloc(AVHWFramesContext *ctx)
static int vt_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc)
Convert an AVColorTransferCharacteristic to a VideoToolbox/CoreVideo color transfer function string.
static int vt_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.
enum AVPixelFormat pixfmt
Definition kmsgrab.c:367
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
static const struct @257111027162314367033347246032313251342043035002 planes[]
uint8_t w
Definition llvidencdsp.c:39
enum AVColorSpace space
enum AVColorRange range
Memory handling functions.
const char data[16]
Definition mxf.c:149
const char * av_color_space_name(enum AVColorSpace space)
Definition pixdesc.c:3860
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
const char * av_color_transfer_name(enum AVColorTransferCharacteristic transfer)
Definition pixdesc.c:3827
const char * av_color_primaries_name(enum AVColorPrimaries primaries)
Definition pixdesc.c:3794
pixel format definitions
AVChromaLocation
Location of chroma samples.
Definition pixfmt.h:802
@ AVCHROMA_LOC_TOP
Definition pixfmt.h:807
@ AVCHROMA_LOC_BOTTOM
Definition pixfmt.h:809
@ AVCHROMA_LOC_TOPLEFT
ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2.
Definition pixfmt.h:806
@ AVCHROMA_LOC_LEFT
MPEG-2/4 4:2:0, H.264 default for 4:2:0.
Definition pixfmt.h:804
@ AVCHROMA_LOC_BOTTOMLEFT
Definition pixfmt.h:808
@ AVCHROMA_LOC_CENTER
MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0.
Definition pixfmt.h:805
AVColorRange
Visual content value range.
Definition pixfmt.h:748
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_UNSPECIFIED
Definition pixfmt.h:749
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_P210
Definition pixfmt.h:622
#define AV_PIX_FMT_P216
Definition pixfmt.h:626
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
#define AV_PIX_FMT_BAYER_RGGB16
Definition pixfmt.h:578
#define AV_PIX_FMT_P410
Definition pixfmt.h:623
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_VIDEOTOOLBOX
hardware decoding through Videotoolbox
Definition pixfmt.h:305
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:371
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:198
@ AV_PIX_FMT_AYUV
packed AYUV 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), AYUVAYUV...
Definition pixfmt.h:442
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
#define AV_PIX_FMT_P416
Definition pixfmt.h:627
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
@ AVCOL_PRI_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
Definition pixfmt.h:649
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition pixfmt.h:644
@ AVCOL_PRI_UNSPECIFIED
Definition pixfmt.h:645
@ AVCOL_PRI_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
Definition pixfmt.h:650
@ AVCOL_PRI_BT2020
ITU-R BT2020.
Definition pixfmt.h:653
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition pixfmt.h:689
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
Definition pixfmt.h:677
@ AVCOL_TRC_SMPTE240M
Definition pixfmt.h:680
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
Definition pixfmt.h:678
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
Definition pixfmt.h:693
@ AVCOL_TRC_SMPTE428
SMPTE ST 428-1.
Definition pixfmt.h:691
@ AVCOL_TRC_BT2020_12
ITU-R BT2020 for 12-bit system.
Definition pixfmt.h:688
@ AVCOL_TRC_BT2020_10
ITU-R BT2020 for 10-bit system.
Definition pixfmt.h:687
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
@ AVCOL_TRC_BT709
also ITU-R BT1361
Definition pixfmt.h:674
#define AV_PIX_FMT_AYUV64
Definition pixfmt.h:607
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition pixfmt.h:708
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
Definition pixfmt.h:712
@ AVCOL_SPC_BT2020_CL
ITU-R BT2020 constant luminance system.
Definition pixfmt.h:718
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition pixfmt.h:707
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
Definition pixfmt.h:717
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:709
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition pixfmt.h:713
@ AVCOL_SPC_SMPTE240M
derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries
Definition pixfmt.h:714
formats
Definition signature.h:47
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition hwcontext.h:444
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition hwcontext.h:449
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition hwcontext.h:456
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
enum AVColorRange color_range
AVBufferPool * pool_internal
void * priv
Hardware-specific private data associated with the mapping.
AVFrame * source
A reference to the original source of the mapping.
AVVTFramesContext p
The public AVVTFramesContext.
CVPixelBufferPoolRef pool
#define av_malloc_array(a, b)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static AVFormatContext * ctx
Definition movenc.c:49
static AVDictionary * opts
Definition movenc.c:51
static char buffer[20]
Definition seek.c:32
int size
static enum AVPixelFormat supported_formats[]
static const Range full_range
static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
CFStringRef kCVImageBufferYCbCrMatrix_ITU_R_2020
@ kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020
CFStringRef kCVImageBufferTransferFunction_ITU_R_2020
@ kCVPixelFormatType_420YpCbCr10BiPlanarFullRange