FFmpeg
Loading...
Searching...
No Matches
videotoolbox.c
Go to the documentation of this file.
1/*
2 * Videotoolbox hardware acceleration
3 *
4 * copyright (c) 2012 Sebastien Zwickert
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "config.h"
24#include "config_components.h"
25#include "videotoolbox.h"
28#include "libavutil/mem.h"
29#include "vt_internal.h"
30#include "libavutil/avutil.h"
31#include "libavutil/hwcontext.h"
32#include "libavutil/pixdesc.h"
33#include "bytestream.h"
34#include "decode.h"
35#include "internal.h"
36#include "h264dec.h"
37#include "hevc/hevcdec.h"
38#include "hwaccel_internal.h"
39#include "mpegvideo.h"
40#include "proresdec.h"
41#include "prores_raw.h"
42#include <Availability.h>
43#include <AvailabilityMacros.h>
44#include <TargetConditionals.h>
45
46#ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
47# define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
48#endif
49#ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
50# define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
51#endif
52
53#if !HAVE_KCMVIDEOCODECTYPE_HEVC
54enum { kCMVideoCodecType_HEVC = 'hvc1' };
55#endif
56
57#if !HAVE_KCMVIDEOCODECTYPE_VP9
58enum { kCMVideoCodecType_VP9 = 'vp09' };
59#endif
60
61#if !HAVE_KCMVIDEOCODECTYPE_AV1
62enum { kCMVideoCodecType_AV1 = 'av01' };
63#endif
64
65#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
66
67typedef struct VTHWFrame {
68 CVPixelBufferRef pixbuf;
70} VTHWFrame;
71
72static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
73{
75 av_buffer_unref(&ref->hw_frames_ctx);
76 CVPixelBufferRelease(ref->pixbuf);
77
79}
80
82 const uint8_t *buffer,
83 uint32_t size)
84{
85 void *tmp;
86
88 &vtctx->allocated_size,
89 size);
90
91 if (!tmp)
92 return AVERROR(ENOMEM);
93
94 vtctx->bitstream = tmp;
95 memcpy(vtctx->bitstream, buffer, size);
96 vtctx->bitstream_size = size;
97
98 return 0;
99}
100
102 const uint8_t *buffer,
103 uint32_t size)
104{
105 void *tmp;
106
108 &vtctx->allocated_size,
109 vtctx->bitstream_size + size);
110
111 if (!tmp)
112 return AVERROR(ENOMEM);
113
114 vtctx->bitstream = tmp;
115 memcpy(vtctx->bitstream + vtctx->bitstream_size, buffer, size);
116 vtctx->bitstream_size += size;
117
118 return 0;
119}
120
122{
123 int ret;
124 VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data;
125
126 if (!ref->pixbuf) {
127 av_log(avctx, AV_LOG_ERROR, "No frame decoded?\n");
129 return AVERROR_EXTERNAL;
130 }
131
132 frame->crop_right = 0;
133 frame->crop_left = 0;
134 frame->crop_top = 0;
135 frame->crop_bottom = 0;
136
137 if ((ret = av_vt_pixbuf_set_attachments(avctx, ref->pixbuf, frame)) < 0)
138 return ret;
139
140 frame->data[3] = (uint8_t*)ref->pixbuf;
141
142 if (ref->hw_frames_ctx) {
143 av_buffer_unref(&frame->hw_frames_ctx);
144 frame->hw_frames_ctx = av_buffer_ref(ref->hw_frames_ctx);
145 if (!frame->hw_frames_ctx)
146 return AVERROR(ENOMEM);
147 }
148
149 return 0;
150}
151
153{
154 size_t size = sizeof(VTHWFrame);
155 uint8_t *data = NULL;
156 AVBufferRef *buf = NULL;
157 int ret = ff_attach_decode_data(avctx, frame);
158 FrameDecodeData *fdd;
159 if (ret < 0)
160 return ret;
161
163 if (!data)
164 return AVERROR(ENOMEM);
166 if (!buf) {
167 av_freep(&data);
168 return AVERROR(ENOMEM);
169 }
170 frame->buf[0] = buf;
171
172 fdd = frame->private_ref;
174
175 frame->width = avctx->width;
176 frame->height = avctx->height;
177 frame->format = avctx->pix_fmt;
178
179 return 0;
180}
181
182#define AV_W8(p, v) *(p) = (v)
183
184static int escape_ps(uint8_t* dst, const uint8_t* src, int src_size)
185{
186 int i;
187 int size = src_size;
188 uint8_t* p = dst;
189
190 for (i = 0; i < src_size; i++) {
191 if (i + 2 < src_size &&
192 src[i] == 0x00 &&
193 src[i + 1] == 0x00 &&
194 src[i + 2] <= 0x03) {
195 if (dst) {
196 *p++ = src[i++];
197 *p++ = src[i];
198 *p++ = 0x03;
199 } else {
200 i++;
201 }
202 size++;
203 } else if (dst)
204 *p++ = src[i];
205 }
206
207 if (dst)
208 av_assert0((p - dst) == size);
209
210 return size;
211}
212
214{
215 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
216 H264Context *h = avctx->priv_data;
217 CFDataRef data = NULL;
218 uint8_t *p;
219 int sps_size = escape_ps(NULL, h->ps.sps->data, h->ps.sps->data_size);
220 int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size);
221 int vt_extradata_size;
222 uint8_t *vt_extradata;
223
224 vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size;
225 vt_extradata = av_malloc(vt_extradata_size);
226
227 if (!vt_extradata)
228 return NULL;
229
230 p = vt_extradata;
231
232 AV_W8(p + 0, 1); /* version */
233 AV_W8(p + 1, h->ps.sps->data[1]); /* profile */
234 AV_W8(p + 2, h->ps.sps->data[2]); /* profile compat */
235 AV_W8(p + 3, h->ps.sps->data[3]); /* level */
236 AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */
237 AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
238 AV_WB16(p + 6, sps_size);
239 p += 8;
240 p += escape_ps(p, h->ps.sps->data, h->ps.sps->data_size);
241 AV_W8(p + 0, 1); /* number of pps */
242 AV_WB16(p + 1, pps_size);
243 p += 3;
244 p += escape_ps(p, h->ps.pps->data, h->ps.pps->data_size);
245
246 av_assert0(p - vt_extradata == vt_extradata_size);
247
248 // save sps header (profile/level) used to create decoder session,
249 // so we can detect changes and recreate it.
250 if (vtctx)
251 memcpy(vtctx->sps, h->ps.sps->data + 1, 3);
252
253 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
254 av_free(vt_extradata);
255 return data;
256}
257
259{
260 HEVCContext *h = avctx->priv_data;
261 int i, num_vps = 0, num_sps = 0, num_pps = 0;
262 const HEVCPPS *pps = h->pps;
263 const HEVCSPS *sps = pps->sps;
264 const HEVCVPS *vps = sps->vps;
265 PTLCommon ptlc = vps->ptl.general_ptl;
266 VUI vui = sps->vui;
267 uint8_t parallelismType;
268 CFDataRef data = NULL;
269 uint8_t *p;
270 int vt_extradata_size = 23 + 3 + 3 + 3;
271 uint8_t *vt_extradata;
272
273#define COUNT_SIZE_PS(T, t) \
274 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
275 if (h->ps.t##ps_list[i]) { \
276 const HEVC##T##PS *lps = h->ps.t##ps_list[i]; \
277 vt_extradata_size += 2 + escape_ps(NULL, lps->data, lps->data_size); \
278 num_##t##ps++; \
279 } \
280 }
281
282 COUNT_SIZE_PS(V, v)
284 COUNT_SIZE_PS(P, p)
285
286 vt_extradata = av_malloc(vt_extradata_size);
287 if (!vt_extradata)
288 return NULL;
289 p = vt_extradata;
290
291 /* unsigned int(8) configurationVersion = 1; */
292 AV_W8(p + 0, 1);
293
294 /*
295 * unsigned int(2) general_profile_space;
296 * unsigned int(1) general_tier_flag;
297 * unsigned int(5) general_profile_idc;
298 */
299 AV_W8(p + 1, ptlc.profile_space << 6 |
300 ptlc.tier_flag << 5 |
301 ptlc.profile_idc);
302
303 /* unsigned int(32) general_profile_compatibility_flags; */
304 for (i = 0; i < 4; i++) {
305 AV_W8(p + 2 + i, ptlc.profile_compatibility_flag[i * 8] << 7 |
306 ptlc.profile_compatibility_flag[i * 8 + 1] << 6 |
307 ptlc.profile_compatibility_flag[i * 8 + 2] << 5 |
308 ptlc.profile_compatibility_flag[i * 8 + 3] << 4 |
309 ptlc.profile_compatibility_flag[i * 8 + 4] << 3 |
310 ptlc.profile_compatibility_flag[i * 8 + 5] << 2 |
311 ptlc.profile_compatibility_flag[i * 8 + 6] << 1 |
312 ptlc.profile_compatibility_flag[i * 8 + 7]);
313 }
314
315 /* unsigned int(48) general_constraint_indicator_flags; */
316 AV_W8(p + 6, ptlc.progressive_source_flag << 7 |
317 ptlc.interlaced_source_flag << 6 |
320 AV_W8(p + 7, 0);
321 AV_WN32(p + 8, 0);
322
323 /* unsigned int(8) general_level_idc; */
324 AV_W8(p + 12, ptlc.level_idc);
325
326 /*
327 * bit(4) reserved = ‘1111’b;
328 * unsigned int(12) min_spatial_segmentation_idc;
329 */
330 AV_W8(p + 13, 0xf0 | (vui.min_spatial_segmentation_idc >> 4));
331 AV_W8(p + 14, vui.min_spatial_segmentation_idc & 0xff);
332
333 /*
334 * bit(6) reserved = ‘111111’b;
335 * unsigned int(2) parallelismType;
336 */
338 parallelismType = 0;
339 else if (pps->entropy_coding_sync_enabled_flag && pps->tiles_enabled_flag)
340 parallelismType = 0;
341 else if (pps->entropy_coding_sync_enabled_flag)
342 parallelismType = 3;
343 else if (pps->tiles_enabled_flag)
344 parallelismType = 2;
345 else
346 parallelismType = 1;
347 AV_W8(p + 15, 0xfc | parallelismType);
348
349 /*
350 * bit(6) reserved = ‘111111’b;
351 * unsigned int(2) chromaFormat;
352 */
353 AV_W8(p + 16, sps->chroma_format_idc | 0xfc);
354
355 /*
356 * bit(5) reserved = ‘11111’b;
357 * unsigned int(3) bitDepthLumaMinus8;
358 */
359 AV_W8(p + 17, (sps->bit_depth - 8) | 0xf8);
360
361 /*
362 * bit(5) reserved = ‘11111’b;
363 * unsigned int(3) bitDepthChromaMinus8;
364 */
365 AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xf8);
366
367 /* bit(16) avgFrameRate; */
368 AV_WB16(p + 19, 0);
369
370 /*
371 * bit(2) constantFrameRate;
372 * bit(3) numTemporalLayers;
373 * bit(1) temporalIdNested;
374 * unsigned int(2) lengthSizeMinusOne;
375 */
376 AV_W8(p + 21, 0 << 6 |
377 sps->max_sub_layers << 3 |
378 sps->temporal_id_nesting << 2 |
379 3);
380
381 /* unsigned int(8) numOfArrays; */
382 AV_W8(p + 22, 3);
383
384 p += 23;
385
386#define APPEND_PS(T, t) \
387 /* \
388 * bit(1) array_completeness; \
389 * unsigned int(1) reserved = 0; \
390 * unsigned int(6) NAL_unit_type; \
391 */ \
392 AV_W8(p, 1 << 7 | \
393 HEVC_NAL_##T##PS & 0x3f); \
394 /* unsigned int(16) numNalus; */ \
395 AV_WB16(p + 1, num_##t##ps); \
396 p += 3; \
397 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
398 if (h->ps.t##ps_list[i]) { \
399 const HEVC##T##PS *lps = h->ps.t##ps_list[i]; \
400 int size = escape_ps(p + 2, lps->data, lps->data_size); \
401 /* unsigned int(16) nalUnitLength; */ \
402 AV_WB16(p, size); \
403 /* bit(8*nalUnitLength) nalUnit; */ \
404 p += 2 + size; \
405 } \
406 }
407
408 APPEND_PS(V, v)
409 APPEND_PS(S, s)
410 APPEND_PS(P, p)
411
412 av_assert0(p - vt_extradata == vt_extradata_size);
413
414 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
415 av_free(vt_extradata);
416 return data;
417}
418
420 const AVBufferRef *buffer_ref,
421 const uint8_t *buffer,
422 uint32_t size)
423{
424 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
425 H264Context *h = avctx->priv_data;
426
427 if (h->is_avc == 1) {
429 }
431 return 0;
432}
433
435 int type,
436 const uint8_t *buffer,
437 uint32_t size)
438{
439 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
440 H264Context *h = avctx->priv_data;
441
442 // save sps header (profile/level) used to create decoder session
443 if (!vtctx->sps[0])
444 memcpy(vtctx->sps, h->ps.sps->data + 1, 3);
445
446 if (type == H264_NAL_SPS) {
447 if (size > 4 && memcmp(vtctx->sps, buffer + 1, 3) != 0) {
448 vtctx->reconfig_needed = true;
449 memcpy(vtctx->sps, buffer + 1, 3);
450 }
451 }
452
453 // pass-through SPS/PPS changes to the decoder
455}
456
458 const uint8_t *buffer,
459 uint32_t size)
460{
461 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
462 void *tmp;
463
465 &vtctx->allocated_size,
466 vtctx->bitstream_size+size+4);
467 if (!tmp)
468 return AVERROR(ENOMEM);
469
470 vtctx->bitstream = tmp;
471
472 AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size);
473 memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size);
474
475 vtctx->bitstream_size += size + 4;
477 return 0;
478}
479
481 const uint8_t *buffer,
482 uint32_t size)
483{
484 H264Context *h = avctx->priv_data;
485
486 if (h->is_avc == 1)
487 return 0;
488
490}
491
492#if CONFIG_VIDEOTOOLBOX
493// Return the AVVideotoolboxContext that matters currently. Where it comes from
494// depends on the API used.
495static AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx)
496{
497 // Somewhat tricky because the user can call av_videotoolbox_default_free()
498 // at any time, even when the codec is closed.
499 if (avctx->internal && avctx->internal->hwaccel_priv_data) {
500 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
501 if (vtctx->vt_ctx)
502 return vtctx->vt_ctx;
503 }
504 return avctx->hwaccel_context;
505}
506
507static void videotoolbox_stop(AVCodecContext *avctx)
508{
509 AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
510 if (!videotoolbox)
511 return;
512
513 if (videotoolbox->cm_fmt_desc) {
514 CFRelease(videotoolbox->cm_fmt_desc);
515 videotoolbox->cm_fmt_desc = NULL;
516 }
517
518 if (videotoolbox->session) {
519 VTDecompressionSessionInvalidate(videotoolbox->session);
520 CFRelease(videotoolbox->session);
521 videotoolbox->session = NULL;
522 }
523}
524
526{
527 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
528 if (!vtctx)
529 return 0;
530
531 av_freep(&vtctx->bitstream);
532 if (vtctx->frame)
533 CVPixelBufferRelease(vtctx->frame);
534
535 if (vtctx->vt_ctx)
536 videotoolbox_stop(avctx);
537
539 av_freep(&vtctx->vt_ctx);
540
541 return 0;
542}
543
544static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
545{
546 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
547 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->frame;
548 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
549 enum AVPixelFormat sw_format = av_map_videotoolbox_format_to_pixfmt(pixel_format);
550 int width = CVPixelBufferGetWidth(pixbuf);
551 int height = CVPixelBufferGetHeight(pixbuf);
552 AVHWFramesContext *cached_frames;
553 VTHWFrame *ref;
554 int ret;
555
556 if (!frame->buf[0] || frame->data[3]) {
557 av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n");
559 return AVERROR_EXTERNAL;
560 }
561
562 ref = (VTHWFrame *)frame->buf[0]->data;
563
564 if (ref->pixbuf)
565 CVPixelBufferRelease(ref->pixbuf);
566 ref->pixbuf = vtctx->frame;
567 vtctx->frame = NULL;
568
569 // Old API code path.
570 if (!vtctx->cached_hw_frames_ctx)
571 return 0;
572
573 cached_frames = (AVHWFramesContext*)vtctx->cached_hw_frames_ctx->data;
574
575 if (cached_frames->sw_format != sw_format ||
576 cached_frames->width != width ||
577 cached_frames->height != height) {
578 AVBufferRef *hw_frames_ctx = av_hwframe_ctx_alloc(cached_frames->device_ref);
579 AVHWFramesContext *hw_frames;
580 AVVTFramesContext *hw_ctx;
581 if (!hw_frames_ctx)
582 return AVERROR(ENOMEM);
583
584 hw_frames = (AVHWFramesContext*)hw_frames_ctx->data;
585 hw_frames->format = cached_frames->format;
586 hw_frames->sw_format = sw_format;
587 hw_frames->width = width;
588 hw_frames->height = height;
589 hw_ctx = hw_frames->hwctx;
590 hw_ctx->color_range = avctx->color_range;
591
592 ret = av_hwframe_ctx_init(hw_frames_ctx);
593 if (ret < 0) {
594 av_buffer_unref(&hw_frames_ctx);
595 return ret;
596 }
597
599 vtctx->cached_hw_frames_ctx = hw_frames_ctx;
600 }
601
602 av_buffer_unref(&ref->hw_frames_ctx);
603 ref->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx);
604 if (!ref->hw_frames_ctx)
605 return AVERROR(ENOMEM);
606
607 return 0;
608}
609
610static void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length)
611{
612 int i;
613 uint8_t b;
614
615 for (i = 3; i >= 0; i--) {
616 b = (length >> (i * 7)) & 0x7F;
617 if (i != 0)
618 b |= 0x80;
619
620 bytestream2_put_byteu(pb, b);
621 }
622}
623
624static CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx)
625{
626 CFDataRef data;
627 uint8_t *rw_extradata;
629 int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3;
630 // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
631 int config_size = 13 + 5 + avctx->extradata_size;
632 int s;
633
634 if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING)))
635 return NULL;
636
637 bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING);
638 bytestream2_put_byteu(&pb, 0); // version
639 bytestream2_put_ne24(&pb, 0); // flags
640
641 // elementary stream descriptor
642 bytestream2_put_byteu(&pb, 0x03); // ES_DescrTag
643 videotoolbox_write_mp4_descr_length(&pb, full_size);
644 bytestream2_put_ne16(&pb, 0); // esid
645 bytestream2_put_byteu(&pb, 0); // stream priority (0-32)
646
647 // decoder configuration descriptor
648 bytestream2_put_byteu(&pb, 0x04); // DecoderConfigDescrTag
649 videotoolbox_write_mp4_descr_length(&pb, config_size);
650 bytestream2_put_byteu(&pb, 32); // object type indication. 32 = AV_CODEC_ID_MPEG4
651 bytestream2_put_byteu(&pb, 0x11); // stream type
652 bytestream2_put_ne24(&pb, 0); // buffer size
653 bytestream2_put_ne32(&pb, 0); // max bitrate
654 bytestream2_put_ne32(&pb, 0); // avg bitrate
655
656 // decoder specific descriptor
657 bytestream2_put_byteu(&pb, 0x05); ///< DecSpecificInfoTag
658 videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size);
659
661
662 // SLConfigDescriptor
663 bytestream2_put_byteu(&pb, 0x06); // SLConfigDescrTag
664 bytestream2_put_byteu(&pb, 0x01); // length
665 bytestream2_put_byteu(&pb, 0x02); //
666
667 s = bytestream2_size_p(&pb);
668
669 data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
670
671 av_freep(&rw_extradata);
672 return data;
673}
674
675static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
676 void *buffer,
677 int size)
678{
679 OSStatus status;
680 CMBlockBufferRef block_buf;
681 CMSampleBufferRef sample_buf;
682
683 block_buf = NULL;
684 sample_buf = NULL;
685
686 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator
687 buffer, // memoryBlock
688 size, // blockLength
689 kCFAllocatorNull, // blockAllocator
690 NULL, // customBlockSource
691 0, // offsetToData
692 size, // dataLength
693 0, // flags
694 &block_buf);
695
696 if (!status) {
697 status = CMSampleBufferCreate(kCFAllocatorDefault, // allocator
698 block_buf, // dataBuffer
699 TRUE, // dataReady
700 0, // makeDataReadyCallback
701 0, // makeDataReadyRefcon
702 fmt_desc, // formatDescription
703 1, // numSamples
704 0, // numSampleTimingEntries
705 NULL, // sampleTimingArray
706 0, // numSampleSizeEntries
707 NULL, // sampleSizeArray
708 &sample_buf);
709 }
710
711 if (block_buf)
712 CFRelease(block_buf);
713
714 return sample_buf;
715}
716
717static void videotoolbox_decoder_callback(void *opaque,
718 void *sourceFrameRefCon,
719 OSStatus status,
720 VTDecodeInfoFlags flags,
721 CVImageBufferRef image_buffer,
722 CMTime pts,
723 CMTime duration)
724{
725 VTContext *vtctx = opaque;
726
727 if (vtctx->frame) {
728 CVPixelBufferRelease(vtctx->frame);
729 vtctx->frame = NULL;
730 }
731
732 if (!image_buffer) {
733 // kVTVideoDecoderReferenceMissingErr, defined since the macOS 12 SDKs
734 if (status != -17694)
735 vtctx->reconfig_needed = true;
736
737 av_log(vtctx->logctx, status ? AV_LOG_WARNING : AV_LOG_DEBUG,
738 "vt decoder cb: output image buffer is null: %i, reconfig %d\n",
739 status, vtctx->reconfig_needed);
740 return;
741 }
742
743 vtctx->frame = CVPixelBufferRetain(image_buffer);
744}
745
746static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx)
747{
748 OSStatus status;
749 CMSampleBufferRef sample_buf;
750 AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
751 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
752
753 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc,
754 vtctx->bitstream,
755 vtctx->bitstream_size);
756
757 if (!sample_buf)
758 return -1;
759
760 status = VTDecompressionSessionDecodeFrame(videotoolbox->session,
761 sample_buf,
762 0, // decodeFlags
763 NULL, // sourceFrameRefCon
764 0); // infoFlagsOut
765 if (status == noErr)
766 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session);
767
768 CFRelease(sample_buf);
769
770 return status;
771}
772
773static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
774 CFDictionaryRef decoder_spec,
775 int width,
776 int height)
777{
778 CMFormatDescriptionRef cm_fmt_desc;
779 OSStatus status;
780
781 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
783 width,
784 height,
785 decoder_spec, // Dictionary of extension
786 &cm_fmt_desc);
787
788 if (status)
789 return NULL;
790
791 return cm_fmt_desc;
792}
793
794static CFDictionaryRef videotoolbox_buffer_attributes_create(int width,
795 int height,
796 OSType pix_fmt)
797{
798 CFMutableDictionaryRef buffer_attributes;
799 CFMutableDictionaryRef io_surface_properties;
800 CFNumberRef cv_pix_fmt;
801 CFNumberRef w;
802 CFNumberRef h;
803
804 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
805 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
806 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
807
808 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
809 4,
810 &kCFTypeDictionaryKeyCallBacks,
811 &kCFTypeDictionaryValueCallBacks);
812 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
813 0,
814 &kCFTypeDictionaryKeyCallBacks,
815 &kCFTypeDictionaryValueCallBacks);
816
817 if (pix_fmt)
818 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
819 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
820 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
821 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
822#if TARGET_OS_IPHONE
823 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
824#else
825 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
826#endif
827
828 CFRelease(io_surface_properties);
829 CFRelease(cv_pix_fmt);
830 CFRelease(w);
831 CFRelease(h);
832
833 return buffer_attributes;
834}
835
836static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type,
837 AVCodecContext *avctx)
838{
839 CFMutableDictionaryRef avc_info;
840 CFDataRef data = NULL;
841
842 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
843 0,
844 &kCFTypeDictionaryKeyCallBacks,
845 &kCFTypeDictionaryValueCallBacks);
846
847 CFDictionarySetValue(config_info,
848 avctx->codec_id == AV_CODEC_ID_HEVC
849 || avctx->codec_id == AV_CODEC_ID_PRORES
851 ?
854 kCFBooleanTrue);
855
856 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
857 1,
858 &kCFTypeDictionaryKeyCallBacks,
859 &kCFTypeDictionaryValueCallBacks);
860
861 switch (codec_type) {
862 case kCMVideoCodecType_MPEG4Video :
863 if (avctx->extradata_size)
864 data = videotoolbox_esds_extradata_create(avctx);
865 if (data)
866 CFDictionarySetValue(avc_info, CFSTR("esds"), data);
867 break;
868 case kCMVideoCodecType_H264 :
870 if (data)
871 CFDictionarySetValue(avc_info, CFSTR("avcC"), data);
872 break;
875 if (data)
876 CFDictionarySetValue(avc_info, CFSTR("hvcC"), data);
877 break;
878#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL
881 if (data)
882 CFDictionarySetValue(avc_info, CFSTR("vpcC"), data);
883 break;
884#endif
885#if CONFIG_AV1_VIDEOTOOLBOX_HWACCEL
888 if (data)
889 CFDictionarySetValue(avc_info, CFSTR("av1C"), data);
890 break;
891#endif
892 default:
893 break;
894 }
895
896 CFDictionarySetValue(config_info,
897 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
898 avc_info);
899
900 if (data)
901 CFRelease(data);
902
903 CFRelease(avc_info);
904 return config_info;
905}
906
907static int videotoolbox_start(AVCodecContext *avctx)
908{
909 AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
910 OSStatus status;
911 VTDecompressionOutputCallbackRecord decoder_cb;
912 CFDictionaryRef decoder_spec;
913 CFDictionaryRef buf_attr;
914
915 if (!videotoolbox) {
916 av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n");
917 return -1;
918 }
919
920 switch( avctx->codec_id ) {
921 case AV_CODEC_ID_H263 :
922 videotoolbox->cm_codec_type = kCMVideoCodecType_H263;
923 break;
924 case AV_CODEC_ID_H264 :
925 videotoolbox->cm_codec_type = kCMVideoCodecType_H264;
926 break;
927 case AV_CODEC_ID_HEVC :
929 break;
931 videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video;
932 break;
934 videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video;
935 break;
936 case AV_CODEC_ID_MPEG4 :
937 videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video;
938 break;
939 case AV_CODEC_ID_PRORES :
940 switch (avctx->codec_tag) {
941 default:
942 av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag);
944 case MKTAG('a','p','c','o'): // kCMVideoCodecType_AppleProRes422Proxy
945 case MKTAG('a','p','c','s'): // kCMVideoCodecType_AppleProRes422LT
946 case MKTAG('a','p','c','n'): // kCMVideoCodecType_AppleProRes422
947 case MKTAG('a','p','c','h'): // kCMVideoCodecType_AppleProRes422HQ
948 case MKTAG('a','p','4','h'): // kCMVideoCodecType_AppleProRes4444
949 case MKTAG('a','p','4','x'): // kCMVideoCodecType_AppleProRes4444XQ
950 videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag);
951 break;
952 }
953 break;
955 videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag);
956 break;
957 case AV_CODEC_ID_VP9 :
958 videotoolbox->cm_codec_type = kCMVideoCodecType_VP9;
959 break;
960 case AV_CODEC_ID_AV1 :
961 videotoolbox->cm_codec_type = kCMVideoCodecType_AV1;
962 break;
963 default :
964 break;
965 }
966
967#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) && AV_HAS_BUILTIN(__builtin_available)
968 if (avctx->codec_id == AV_CODEC_ID_PRORES || avctx->codec_id == AV_CODEC_ID_PRORES_RAW) {
969 if (__builtin_available(macOS 10.9, *)) {
970 VTRegisterProfessionalVideoWorkflowVideoDecoders();
971 }
972 }
973#endif
974
975#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) && AV_HAS_BUILTIN(__builtin_available)
976 if (__builtin_available(macOS 11.0, *)) {
977 VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type);
978 }
979#endif
980
981 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx);
982
983 if (!decoder_spec) {
984 av_log(avctx, AV_LOG_ERROR, "decoder specification creation failed\n");
985 return -1;
986 }
987
988 videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type,
989 decoder_spec,
990 avctx->width,
991 avctx->height);
992 if (!videotoolbox->cm_fmt_desc) {
993 if (decoder_spec)
994 CFRelease(decoder_spec);
995
996 av_log(avctx, AV_LOG_ERROR, "format description creation failed\n");
997 return -1;
998 }
999
1000 buf_attr = videotoolbox_buffer_attributes_create(avctx->width,
1001 avctx->height,
1002 videotoolbox->cv_pix_fmt_type);
1003
1004 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
1005 decoder_cb.decompressionOutputRefCon = avctx->internal->hwaccel_priv_data;
1006
1007 status = VTDecompressionSessionCreate(NULL, // allocator
1008 videotoolbox->cm_fmt_desc, // videoFormatDescription
1009 decoder_spec, // videoDecoderSpecification
1010 buf_attr, // destinationImageBufferAttributes
1011 &decoder_cb, // outputCallback
1012 &videotoolbox->session); // decompressionSessionOut
1013
1014 if (decoder_spec)
1015 CFRelease(decoder_spec);
1016 if (buf_attr)
1017 CFRelease(buf_attr);
1018
1019 switch (status) {
1020 case kVTVideoDecoderNotAvailableNowErr:
1021 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox session not available.\n");
1022 return AVERROR(ENOSYS);
1023 case kVTVideoDecoderUnsupportedDataFormatErr:
1024 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox does not support this format.\n");
1025 return AVERROR(ENOSYS);
1026 case kVTCouldNotFindVideoDecoderErr:
1027 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder for this format not found.\n");
1028 return AVERROR(ENOSYS);
1029 case kVTVideoDecoderMalfunctionErr:
1030 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n");
1031 return AVERROR(EINVAL);
1032 case kVTVideoDecoderBadDataErr:
1033 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n");
1034 return AVERROR_INVALIDDATA;
1035 case 0:
1036 return 0;
1037 default:
1038 av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %d\n", (int)status);
1039 return AVERROR_UNKNOWN;
1040 }
1041}
1042
1043static const char *videotoolbox_error_string(OSStatus status)
1044{
1045 switch (status) {
1046 case kVTVideoDecoderBadDataErr:
1047 return "bad data";
1048 case kVTVideoDecoderMalfunctionErr:
1049 return "decoder malfunction";
1050 case kVTInvalidSessionErr:
1051 return "invalid session";
1052 }
1053 return "unknown";
1054}
1055
1057{
1058 OSStatus status;
1059 AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
1060 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1061
1062 if (vtctx->reconfig_needed == true) {
1063 vtctx->reconfig_needed = false;
1064 av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n");
1065 videotoolbox_stop(avctx);
1066 if (videotoolbox_start(avctx) != 0) {
1067 return AVERROR_EXTERNAL;
1068 }
1069 }
1070
1071 if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size)
1072 return AVERROR_INVALIDDATA;
1073
1074 status = videotoolbox_session_decode_frame(avctx);
1075 if (status != noErr) {
1076 if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr)
1077 vtctx->reconfig_needed = true;
1078 av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status);
1079 return AVERROR_UNKNOWN;
1080 }
1081
1082 if (!vtctx->frame)
1083 return AVERROR_UNKNOWN;
1084
1085 return videotoolbox_buffer_create(avctx, frame);
1086}
1087
1088static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
1089{
1090 H264Context *h = avctx->priv_data;
1091 AVFrame *frame = h->cur_pic_ptr->f;
1092 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1093 int ret = ff_videotoolbox_common_end_frame(avctx, frame);
1094 vtctx->bitstream_size = 0;
1095 return ret;
1096}
1097
1098static int videotoolbox_hevc_start_frame(AVCodecContext *avctx,
1099 const AVBufferRef *buffer_ref,
1100 const uint8_t *buffer,
1101 uint32_t size)
1102{
1103 HEVCContext *h = avctx->priv_data;
1104 AVFrame *frame = h->cur_frame->f;
1105
1106 frame->crop_right = 0;
1107 frame->crop_left = 0;
1108 frame->crop_top = 0;
1109 frame->crop_bottom = 0;
1110
1111 return 0;
1112}
1113
1114static int videotoolbox_hevc_decode_slice(AVCodecContext *avctx,
1115 const uint8_t *buffer,
1116 uint32_t size)
1117{
1119}
1120
1121
1122static int videotoolbox_hevc_decode_params(AVCodecContext *avctx,
1123 int type,
1124 const uint8_t *buffer,
1125 uint32_t size)
1126{
1128}
1129
1130static int videotoolbox_hevc_end_frame(AVCodecContext *avctx)
1131{
1132 HEVCContext *h = avctx->priv_data;
1133 AVFrame *frame = h->cur_frame->f;
1134 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1135 int ret;
1136
1138 vtctx->bitstream_size = 0;
1139 return ret;
1140}
1141
1142static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx,
1143 const AVBufferRef *buffer_ref,
1144 const uint8_t *buffer,
1145 uint32_t size)
1146{
1147 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1148
1149 return ff_videotoolbox_buffer_copy(vtctx, buffer, size);
1150}
1151
1152static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
1153 const uint8_t *buffer,
1154 uint32_t size)
1155{
1156 return 0;
1157}
1158
1159static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
1160{
1161 MpegEncContext *s = avctx->priv_data;
1162 AVFrame *frame = s->cur_pic.ptr->f;
1163
1165}
1166
1167static int videotoolbox_prores_start_frame(AVCodecContext *avctx,
1168 const AVBufferRef *buffer_ref,
1169 const uint8_t *buffer,
1170 uint32_t size)
1171{
1172 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1173 ProresContext *ctx = avctx->priv_data;
1174
1175 /* Videotoolbox decodes both fields simultaneously */
1176 if (!ctx->first_field)
1177 return 0;
1178
1179 return ff_videotoolbox_buffer_copy(vtctx, buffer, size);
1180}
1181
1182static int videotoolbox_prores_decode_slice(AVCodecContext *avctx,
1183 const uint8_t *buffer,
1184 uint32_t size)
1185{
1186 return 0;
1187}
1188
1189static int videotoolbox_prores_end_frame(AVCodecContext *avctx)
1190{
1191 ProresContext *ctx = avctx->priv_data;
1192 AVFrame *frame = ctx->frame;
1193
1194 if (!ctx->first_field)
1195 return 0;
1196
1198}
1199
1200static int videotoolbox_prores_raw_start_frame(AVCodecContext *avctx,
1201 const AVBufferRef *buffer_ref,
1202 const uint8_t *buffer,
1203 uint32_t size)
1204{
1205 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1206
1207 return ff_videotoolbox_buffer_copy(vtctx, buffer, size);
1208}
1209
1210static int videotoolbox_prores_raw_decode_slice(AVCodecContext *avctx,
1211 const uint8_t *buffer,
1212 uint32_t size)
1213{
1214 return 0;
1215}
1216
1217static int videotoolbox_prores_raw_end_frame(AVCodecContext *avctx)
1218{
1219 ProResRAWContext *ctx = avctx->priv_data;
1220 AVFrame *frame = ctx->frame;
1221
1223}
1224
1225static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) {
1226 int depth;
1227 const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
1228 if (!descriptor)
1229 return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context()
1230
1231 depth = descriptor->comp[0].depth;
1232
1233 if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA)
1234 return (depth > 8) ? AV_PIX_FMT_AYUV64 : AV_PIX_FMT_AYUV;
1235
1236 if (descriptor->flags & AV_PIX_FMT_FLAG_BAYER)
1238
1239#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
1240 if (depth > 10)
1241 return descriptor->log2_chroma_w == 0 ? AV_PIX_FMT_P416 : AV_PIX_FMT_P216;
1242#endif
1243
1244#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
1245 if (descriptor->log2_chroma_w == 0) {
1246#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
1247 if (depth <= 8)
1248 return AV_PIX_FMT_NV24;
1249#endif
1250 return AV_PIX_FMT_P410;
1251 }
1252#endif
1253#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
1254 if (descriptor->log2_chroma_h == 0) {
1255#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
1256 if (depth <= 8)
1257 return AV_PIX_FMT_NV16;
1258#endif
1259 return AV_PIX_FMT_P210;
1260 }
1261#endif
1262#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
1263 if (depth > 8) {
1264 return AV_PIX_FMT_P010;
1265 }
1266#endif
1267
1268 return AV_PIX_FMT_NV12;
1269}
1270
1271static AVVideotoolboxContext *videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt,
1272 bool full_range)
1273{
1274 AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));
1275
1276 if (ret) {
1278 if (cv_pix_fmt_type == 0) {
1279 cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1280 }
1281 ret->cv_pix_fmt_type = cv_pix_fmt_type;
1282 }
1283
1284 return ret;
1285}
1286
1288{
1289 VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1290 AVHWFramesContext *hw_frames;
1291 AVVTFramesContext *hw_ctx;
1292 int err;
1293 bool full_range;
1294
1295 vtctx->logctx = avctx;
1296
1297 if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx &&
1298 avctx->hwaccel_context)
1299 return videotoolbox_start(avctx);
1300
1301 if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
1302 av_log(avctx, AV_LOG_ERROR,
1303 "Either hw_frames_ctx or hw_device_ctx must be set.\n");
1304 return AVERROR(EINVAL);
1305 }
1306
1307 vtctx->vt_ctx = videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false);
1308 if (!vtctx->vt_ctx) {
1309 err = AVERROR(ENOMEM);
1310 goto fail;
1311 }
1312
1313 if (avctx->hw_frames_ctx) {
1314 hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1315 } else {
1317 if (!avctx->hw_frames_ctx) {
1318 err = AVERROR(ENOMEM);
1319 goto fail;
1320 }
1321
1322 hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1323 hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX;
1324 hw_frames->sw_format = videotoolbox_best_pixel_format(avctx);
1325 hw_frames->width = avctx->width;
1326 hw_frames->height = avctx->height;
1327 hw_ctx = hw_frames->hwctx;
1328 hw_ctx->color_range = avctx->color_range;
1329
1330 err = av_hwframe_ctx_init(avctx->hw_frames_ctx);
1331 if (err < 0) {
1333 goto fail;
1334 }
1335 }
1336
1338 if (!vtctx->cached_hw_frames_ctx) {
1339 err = AVERROR(ENOMEM);
1340 goto fail;
1341 }
1342
1344 vtctx->vt_ctx->cv_pix_fmt_type =
1346 if (!vtctx->vt_ctx->cv_pix_fmt_type) {
1347 const AVPixFmtDescriptor *attempted_format =
1348 av_pix_fmt_desc_get(hw_frames->sw_format);
1349 av_log(avctx, AV_LOG_ERROR,
1350 "Failed to map underlying FFmpeg pixel format %s (%s range) to "
1351 "a VideoToolbox format!\n",
1352 attempted_format ? attempted_format->name : "<unknown>",
1354 err = AVERROR(EINVAL);
1355 goto fail;
1356 }
1357
1358 err = videotoolbox_start(avctx);
1359 if (err < 0)
1360 goto fail;
1361
1362 return 0;
1363
1364fail:
1366 return err;
1367}
1368
1370 AVBufferRef *hw_frames_ctx)
1371{
1372 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1373
1374 frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX;
1375 frames_ctx->width = avctx->coded_width;
1376 frames_ctx->height = avctx->coded_height;
1377 frames_ctx->sw_format = videotoolbox_best_pixel_format(avctx);
1378
1379 return 0;
1380}
1381
1383 .p.name = "h263_videotoolbox",
1384 .p.type = AVMEDIA_TYPE_VIDEO,
1385 .p.id = AV_CODEC_ID_H263,
1386 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1387 .alloc_frame = ff_videotoolbox_alloc_frame,
1388 .start_frame = videotoolbox_mpeg_start_frame,
1389 .decode_slice = videotoolbox_mpeg_decode_slice,
1390 .end_frame = videotoolbox_mpeg_end_frame,
1391 .frame_params = ff_videotoolbox_frame_params,
1393 .uninit = ff_videotoolbox_uninit,
1394 .priv_data_size = sizeof(VTContext),
1395};
1396
1398 .p.name = "hevc_videotoolbox",
1399 .p.type = AVMEDIA_TYPE_VIDEO,
1400 .p.id = AV_CODEC_ID_HEVC,
1401 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1402 .alloc_frame = ff_videotoolbox_alloc_frame,
1403 .start_frame = videotoolbox_hevc_start_frame,
1404 .decode_slice = videotoolbox_hevc_decode_slice,
1405 .decode_params = videotoolbox_hevc_decode_params,
1406 .end_frame = videotoolbox_hevc_end_frame,
1407 .frame_params = ff_videotoolbox_frame_params,
1409 .uninit = ff_videotoolbox_uninit,
1410 .priv_data_size = sizeof(VTContext),
1411};
1412
1414 .p.name = "h264_videotoolbox",
1415 .p.type = AVMEDIA_TYPE_VIDEO,
1416 .p.id = AV_CODEC_ID_H264,
1417 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1418 .alloc_frame = ff_videotoolbox_alloc_frame,
1419 .start_frame = ff_videotoolbox_h264_start_frame,
1420 .decode_slice = ff_videotoolbox_h264_decode_slice,
1421 .decode_params = videotoolbox_h264_decode_params,
1422 .end_frame = videotoolbox_h264_end_frame,
1423 .frame_params = ff_videotoolbox_frame_params,
1425 .uninit = ff_videotoolbox_uninit,
1426 .priv_data_size = sizeof(VTContext),
1427};
1428
1430 .p.name = "mpeg1_videotoolbox",
1431 .p.type = AVMEDIA_TYPE_VIDEO,
1432 .p.id = AV_CODEC_ID_MPEG1VIDEO,
1433 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1434 .alloc_frame = ff_videotoolbox_alloc_frame,
1435 .start_frame = videotoolbox_mpeg_start_frame,
1436 .decode_slice = videotoolbox_mpeg_decode_slice,
1437 .end_frame = videotoolbox_mpeg_end_frame,
1438 .frame_params = ff_videotoolbox_frame_params,
1440 .uninit = ff_videotoolbox_uninit,
1441 .priv_data_size = sizeof(VTContext),
1442};
1443
1445 .p.name = "mpeg2_videotoolbox",
1446 .p.type = AVMEDIA_TYPE_VIDEO,
1447 .p.id = AV_CODEC_ID_MPEG2VIDEO,
1448 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1449 .alloc_frame = ff_videotoolbox_alloc_frame,
1450 .start_frame = videotoolbox_mpeg_start_frame,
1451 .decode_slice = videotoolbox_mpeg_decode_slice,
1452 .end_frame = videotoolbox_mpeg_end_frame,
1453 .frame_params = ff_videotoolbox_frame_params,
1455 .uninit = ff_videotoolbox_uninit,
1456 .priv_data_size = sizeof(VTContext),
1457};
1458
1460 .p.name = "mpeg4_videotoolbox",
1461 .p.type = AVMEDIA_TYPE_VIDEO,
1462 .p.id = AV_CODEC_ID_MPEG4,
1463 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1464 .alloc_frame = ff_videotoolbox_alloc_frame,
1465 .start_frame = videotoolbox_mpeg_start_frame,
1466 .decode_slice = videotoolbox_mpeg_decode_slice,
1467 .end_frame = videotoolbox_mpeg_end_frame,
1468 .frame_params = ff_videotoolbox_frame_params,
1470 .uninit = ff_videotoolbox_uninit,
1471 .priv_data_size = sizeof(VTContext),
1472};
1473
1475 .p.name = "prores_videotoolbox",
1476 .p.type = AVMEDIA_TYPE_VIDEO,
1477 .p.id = AV_CODEC_ID_PRORES,
1478 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1479 .alloc_frame = ff_videotoolbox_alloc_frame,
1480 .start_frame = videotoolbox_prores_start_frame,
1481 .decode_slice = videotoolbox_prores_decode_slice,
1482 .end_frame = videotoolbox_prores_end_frame,
1483 .frame_params = ff_videotoolbox_frame_params,
1485 .uninit = ff_videotoolbox_uninit,
1486 .priv_data_size = sizeof(VTContext),
1487};
1488
1490 .p.name = "prores_raw_videotoolbox",
1491 .p.type = AVMEDIA_TYPE_VIDEO,
1492 .p.id = AV_CODEC_ID_PRORES_RAW,
1493 .p.pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
1494 .alloc_frame = ff_videotoolbox_alloc_frame,
1495 .start_frame = videotoolbox_prores_raw_start_frame,
1496 .decode_slice = videotoolbox_prores_raw_decode_slice,
1497 .end_frame = videotoolbox_prores_raw_end_frame,
1498 .frame_params = ff_videotoolbox_frame_params,
1500 .uninit = ff_videotoolbox_uninit,
1501 .priv_data_size = sizeof(VTContext),
1502};
1503
1504#endif /* CONFIG_VIDEOTOOLBOX */
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static AVFormatContext * ctx
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define V
Definition avdct.c:32
Convenience header that includes libavutil's core.
#define bytestream2_put_ne16
Definition bytestream.h:127
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition bytestream.h:147
#define bytestream2_put_ne32
Definition bytestream.h:129
static av_always_inline int bytestream2_size_p(const PutByteContext *p)
Definition bytestream.h:207
#define bytestream2_put_ne24
Definition bytestream.h:128
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size)
Definition bytestream.h:286
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static int FUNC vps(CodedBitstreamContext *ctx, RWContext *rw, H265RawVPS *current)
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame)
Definition decode.c:1704
static enum AVPixelFormat pix_fmt
static AVFrame * frame
uint64_t pps
Definition dovi_rpuenc.c:36
static int64_t duration
Definition ffplay.c:330
#define S(s, c, i)
#define fail
Definition test.h:479
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
@ AV_CODEC_ID_PRORES_RAW
Definition codec_id.h:324
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_PRORES
Definition codec_id.h:198
@ AV_CODEC_ID_H263
Definition codec_id.h:54
@ AV_CODEC_ID_MPEG4
Definition codec_id.h:62
@ AV_CODEC_ID_VP9
Definition codec_id.h:217
@ AV_CODEC_ID_MPEG1VIDEO
Definition codec_id.h:51
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition codec_id.h:52
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
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
#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_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:495
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ H264_NAL_SPS
Definition h264.h:41
H.264 / AVC / MPEG-4 part10 codec.
const struct FFHWAccel ff_mpeg1_videotoolbox_hwaccel
const struct FFHWAccel ff_mpeg4_videotoolbox_hwaccel
const struct FFHWAccel ff_hevc_videotoolbox_hwaccel
const struct FFHWAccel ff_prores_raw_videotoolbox_hwaccel
const struct FFHWAccel ff_h263_videotoolbox_hwaccel
const struct FFHWAccel ff_mpeg2_videotoolbox_hwaccel
const struct FFHWAccel ff_prores_videotoolbox_hwaccel
const struct FFHWAccel ff_h264_videotoolbox_hwaccel
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
cl_device_type type
int av_vt_pixbuf_set_attachments(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src)
enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt)
Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat.
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...
An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.
#define b
Definition input.c:43
#define AV_WN32(p, v)
#define AV_WB32(p, v)
#define AV_WB16(p, v)
common internal api header.
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
uint8_t w
Definition llvidencdsp.c:39
#define MKTAG(a, b, c, d)
Definition macros.h:55
Memory handling functions.
#define P
mpegvideo header.
const char data[16]
Definition mxf.c:149
#define av_malloc(s)
Definition ops_static.c:52
const char * av_color_range_name(enum AVColorRange range)
Definition pixdesc.c:3776
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition pixdesc.h:147
#define AV_PIX_FMT_FLAG_BAYER
The pixel format is following a Bayer pattern.
Definition pixdesc.h:152
@ 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_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
#define AV_PIX_FMT_P416
Definition pixfmt.h:627
#define AV_PIX_FMT_AYUV64
Definition pixfmt.h:607
#define av_bswap32
Definition bswap.h:47
enum AVMediaType codec_type
Definition rtp.c:37
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:650
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition avcodec.h:681
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition avcodec.h:468
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
void * hwaccel_context
Legacy hardware accelerator context.
Definition avcodec.h:1447
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition avcodec.h:1493
enum AVCodecID codec_id
Definition avcodec.h:453
int extradata_size
Definition avcodec.h:527
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition avcodec.h:619
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * hwaccel_priv_data
hwaccel-specific private data
Definition internal.h:130
int depth
Number of bits in the component.
Definition pixdesc.h:57
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition hwcontext.h:129
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
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
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
const char * name
Definition pixdesc.h:70
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition pixdesc.h:105
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition pixdesc.h:80
uint64_t flags
Combination of AV_PIX_FMT_FLAG_... flags.
Definition pixdesc.h:94
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition pixdesc.h:89
enum AVColorRange color_range
This struct holds all the information that needs to be passed between the caller and libavcodec for i...
int cm_codec_type
CoreMedia codec type that Videotoolbox will use to create the decompression session.
CMVideoFormatDescriptionRef cm_fmt_desc
CoreMedia Format Description that Videotoolbox will use to create the decompression session.
OSType cv_pix_fmt_type
CVPixelBuffer Format Type that Videotoolbox will use for decoded frames.
VTDecompressionSessionRef session
Videotoolbox decompression session object.
This struct stores per-frame lavc-internal data and is attached to it via private_ref.
Definition decode.h:33
int(* hwaccel_priv_post_process)(void *logctx, AVFrame *frame)
Per-frame private data for hwaccels.
Definition decode.h:53
H264Context.
Definition h264dec.h:338
Definition ps.h:371
Definition ps.h:252
Definition ps.h:168
MpegEncContext.
Definition mpegvideo.h:67
uint8_t level_idc
Definition ps.h:147
uint8_t frame_only_constraint_flag
Definition ps.h:135
uint8_t progressive_source_flag
Definition ps.h:132
uint8_t interlaced_source_flag
Definition ps.h:133
uint8_t profile_idc
Definition ps.h:130
uint8_t profile_space
Definition ps.h:128
uint8_t tier_flag
Definition ps.h:129
uint8_t profile_compatibility_flag[32]
Definition ps.h:131
uint8_t non_packed_constraint_flag
Definition ps.h:134
void * logctx
Definition vt_internal.h:49
CVImageBufferRef frame
Definition vt_internal.h:36
uint8_t sps[3]
Definition vt_internal.h:46
struct AVBufferRef * cached_hw_frames_ctx
Definition vt_internal.h:39
struct AVVideotoolboxContext * vt_ctx
Definition vt_internal.h:43
bool reconfig_needed
Definition vt_internal.h:47
uint8_t * bitstream
Definition vt_internal.h:27
int bitstream_size
Definition vt_internal.h:30
int allocated_size
Definition vt_internal.h:33
CVPixelBufferRef pixbuf
AVBufferRef * hw_frames_ctx
Definition ps.h:98
int min_spatial_segmentation_idc
Definition ps.h:120
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
static char buffer[20]
Definition seek.c:32
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
static int64_t pts
int size
static const Range full_range
#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING
int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
static int videotoolbox_h264_decode_params(AVCodecContext *avctx, int type, const uint8_t *buffer, uint32_t size)
#define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame)
int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
int ff_videotoolbox_buffer_append(VTContext *vtctx, const uint8_t *buffer, uint32_t size)
static int escape_ps(uint8_t *dst, const uint8_t *src, int src_size)
int ff_videotoolbox_buffer_copy(VTContext *vtctx, const uint8_t *buffer, uint32_t size)
#define COUNT_SIZE_PS(T, t)
@ kCMVideoCodecType_HEVC
int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, const AVBufferRef *buffer_ref, const uint8_t *buffer, uint32_t size)
#define AV_W8(p, v)
#define APPEND_PS(T, t)
#define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
@ kCMVideoCodecType_VP9
static int videotoolbox_common_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
@ kCMVideoCodecType_AV1
CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx)
Public libavcodec Videotoolbox header.
CFDataRef ff_videotoolbox_av1c_extradata_create(AVCodecContext *avctx)
CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx)
int ff_videotoolbox_common_init(AVCodecContext *avctx)
int ff_videotoolbox_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
int ff_videotoolbox_uninit(AVCodecContext *avctx)
int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)