24 #include "config_components.h"
40 #include <Availability.h>
41 #include <AvailabilityMacros.h>
42 #include <TargetConditionals.h>
44 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
45 # define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
47 #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
48 # define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
51 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
55 #if !HAVE_KCMVIDEOCODECTYPE_VP9
59 #if !HAVE_KCMVIDEOCODECTYPE_AV1
63 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
74 CVPixelBufferRelease(
ref->pixbuf);
130 frame->crop_right = 0;
131 frame->crop_left = 0;
133 frame->crop_bottom = 0;
138 frame->data[3] = (uint8_t*)
ref->pixbuf;
140 if (
ref->hw_frames_ctx) {
143 if (!
frame->hw_frames_ctx)
170 fdd =
frame->private_ref;
180 #define AV_W8(p, v) *(p) = (v)
188 for (
i = 0;
i < src_size;
i++) {
189 if (
i + 2 < src_size &&
191 src[
i + 1] == 0x00 &&
192 src[
i + 2] <= 0x03) {
219 int vt_extradata_size;
220 uint8_t *vt_extradata;
222 vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size;
223 vt_extradata =
av_malloc(vt_extradata_size);
231 AV_W8(p + 1,
h->ps.sps->data[1]);
232 AV_W8(p + 2,
h->ps.sps->data[2]);
233 AV_W8(p + 3,
h->ps.sps->data[3]);
238 p +=
escape_ps(p,
h->ps.sps->data,
h->ps.sps->data_size);
242 p +=
escape_ps(p,
h->ps.pps->data,
h->ps.pps->data_size);
244 av_assert0(p - vt_extradata == vt_extradata_size);
249 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
251 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
259 int i, num_vps = 0, num_sps = 0, num_pps = 0;
265 uint8_t parallelismType;
268 int vt_extradata_size = 23 + 3 + 3 + 3;
269 uint8_t *vt_extradata;
271 #define COUNT_SIZE_PS(T, t) \
272 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
273 if (h->ps.t##ps_list[i]) { \
274 const HEVC##T##PS *lps = h->ps.t##ps_list[i]; \
275 vt_extradata_size += 2 + escape_ps(NULL, lps->data, lps->data_size); \
284 vt_extradata =
av_malloc(vt_extradata_size);
302 for (
i = 0;
i < 4;
i++) {
337 else if (
pps->entropy_coding_sync_enabled_flag &&
pps->tiles_enabled_flag)
339 else if (
pps->entropy_coding_sync_enabled_flag)
341 else if (
pps->tiles_enabled_flag)
345 AV_W8(p + 15, 0xfc | parallelismType);
351 AV_W8(p + 16,
sps->chroma_format_idc | 0xfc);
357 AV_W8(p + 17, (
sps->bit_depth - 8) | 0xf8);
363 AV_W8(p + 18, (
sps->bit_depth_chroma - 8) | 0xf8);
374 AV_W8(p + 21, 0 << 6 |
375 sps->max_sub_layers << 3 |
376 sps->temporal_id_nesting << 2 |
384 #define APPEND_PS(T, t) \
391 HEVC_NAL_##T##PS & 0x3f); \
393 AV_WB16(p + 1, num_##t##ps); \
395 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
396 if (h->ps.t##ps_list[i]) { \
397 const HEVC##T##PS *lps = h->ps.t##ps_list[i]; \
398 int size = escape_ps(p + 2, lps->data, lps->data_size); \
410 av_assert0(p - vt_extradata == vt_extradata_size);
412 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
425 if (
h->is_avc == 1) {
442 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
490 #if CONFIG_VIDEOTOOLBOX
517 VTDecompressionSessionInvalidate(videotoolbox->
session);
518 CFRelease(videotoolbox->
session);
531 CVPixelBufferRelease(vtctx->
frame);
534 videotoolbox_stop(avctx);
545 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->
frame;
546 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
548 int width = CVPixelBufferGetWidth(pixbuf);
549 int height = CVPixelBufferGetHeight(pixbuf);
563 CVPixelBufferRelease(
ref->pixbuf);
587 hw_ctx = hw_frames->
hwctx;
602 if (!
ref->hw_frames_ctx)
608 static void videotoolbox_write_mp4_descr_length(
PutByteContext *pb,
int length)
613 for (
i = 3;
i >= 0;
i--) {
614 b = (length >> (
i * 7)) & 0x7F;
618 bytestream2_put_byteu(pb,
b);
622 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
625 uint8_t *rw_extradata;
636 bytestream2_put_byteu(&pb, 0);
640 bytestream2_put_byteu(&pb, 0x03);
641 videotoolbox_write_mp4_descr_length(&pb, full_size);
643 bytestream2_put_byteu(&pb, 0);
646 bytestream2_put_byteu(&pb, 0x04);
647 videotoolbox_write_mp4_descr_length(&pb, config_size);
648 bytestream2_put_byteu(&pb, 32);
649 bytestream2_put_byteu(&pb, 0x11);
655 bytestream2_put_byteu(&pb, 0x05);
661 bytestream2_put_byteu(&pb, 0x06);
662 bytestream2_put_byteu(&pb, 0x01);
663 bytestream2_put_byteu(&pb, 0x02);
667 data = CFDataCreate(kCFAllocatorDefault, rw_extradata,
s);
673 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
678 CMBlockBufferRef block_buf;
679 CMSampleBufferRef sample_buf;
684 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
695 status = CMSampleBufferCreate(kCFAllocatorDefault,
710 CFRelease(block_buf);
715 static void videotoolbox_decoder_callback(
void *opaque,
716 void *sourceFrameRefCon,
718 VTDecodeInfoFlags
flags,
719 CVImageBufferRef image_buffer,
726 CVPixelBufferRelease(vtctx->
frame);
736 "vt decoder cb: output image buffer is null: %i, reconfig %d\n",
741 vtctx->
frame = CVPixelBufferRetain(image_buffer);
744 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
747 CMSampleBufferRef sample_buf;
751 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
758 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
764 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
766 CFRelease(sample_buf);
771 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType
codec_type,
772 CFDictionaryRef decoder_spec,
776 CMFormatDescriptionRef cm_fmt_desc;
779 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
792 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
796 CFMutableDictionaryRef buffer_attributes;
797 CFMutableDictionaryRef io_surface_properties;
798 CFNumberRef cv_pix_fmt;
802 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
width);
803 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
height);
804 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
pix_fmt);
806 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
808 &kCFTypeDictionaryKeyCallBacks,
809 &kCFTypeDictionaryValueCallBacks);
810 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
812 &kCFTypeDictionaryKeyCallBacks,
813 &kCFTypeDictionaryValueCallBacks);
816 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
817 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
818 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey,
w);
819 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey,
h);
821 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
823 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
826 CFRelease(io_surface_properties);
827 CFRelease(cv_pix_fmt);
831 return buffer_attributes;
834 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
837 CFMutableDictionaryRef avc_info;
840 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
842 &kCFTypeDictionaryKeyCallBacks,
843 &kCFTypeDictionaryValueCallBacks);
845 CFDictionarySetValue(config_info,
851 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
853 &kCFTypeDictionaryKeyCallBacks,
854 &kCFTypeDictionaryValueCallBacks);
857 case kCMVideoCodecType_MPEG4Video :
859 data = videotoolbox_esds_extradata_create(avctx);
861 CFDictionarySetValue(avc_info, CFSTR(
"esds"),
data);
863 case kCMVideoCodecType_H264 :
866 CFDictionarySetValue(avc_info, CFSTR(
"avcC"),
data);
871 CFDictionarySetValue(avc_info, CFSTR(
"hvcC"),
data);
873 #if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL
877 CFDictionarySetValue(avc_info, CFSTR(
"vpcC"),
data);
880 #if CONFIG_AV1_VIDEOTOOLBOX_HWACCEL
884 CFDictionarySetValue(avc_info, CFSTR(
"av1C"),
data);
891 CFDictionarySetValue(config_info,
892 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
906 VTDecompressionOutputCallbackRecord decoder_cb;
907 CFDictionaryRef decoder_spec;
908 CFDictionaryRef buf_attr;
939 case MKTAG(
'a',
'p',
'c',
'o'):
940 case
MKTAG(
'a',
'p',
'c',
's'):
941 case
MKTAG(
'a',
'p',
'c',
'n'):
942 case
MKTAG(
'a',
'p',
'c',
'h'):
943 case
MKTAG(
'a',
'p',
'4',
'h'):
944 case
MKTAG(
'a',
'p',
'4',
'x'):
945 videotoolbox->cm_codec_type =
av_bswap32(avctx->codec_tag);
959 #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)
961 if (__builtin_available(macOS 10.9, *)) {
962 VTRegisterProfessionalVideoWorkflowVideoDecoders();
967 #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)
968 if (__builtin_available(macOS 11.0, *)) {
969 VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->
cm_codec_type);
973 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
986 CFRelease(decoder_spec);
992 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
996 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
1007 CFRelease(decoder_spec);
1009 CFRelease(buf_attr);
1012 case kVTVideoDecoderNotAvailableNowErr:
1015 case kVTVideoDecoderUnsupportedDataFormatErr:
1018 case kVTCouldNotFindVideoDecoderErr:
1021 case kVTVideoDecoderMalfunctionErr:
1024 case kVTVideoDecoderBadDataErr:
1035 static const char *videotoolbox_error_string(OSStatus
status)
1038 case kVTVideoDecoderBadDataErr:
1040 case kVTVideoDecoderMalfunctionErr:
1041 return "decoder malfunction";
1042 case kVTInvalidSessionErr:
1043 return "invalid session";
1057 videotoolbox_stop(avctx);
1058 if (videotoolbox_start(avctx) != 0) {
1066 status = videotoolbox_session_decode_frame(avctx);
1068 if (
status == kVTVideoDecoderMalfunctionErr ||
status == kVTInvalidSessionErr)
1077 return videotoolbox_buffer_create(avctx,
frame);
1098 frame->crop_right = 0;
1099 frame->crop_left = 0;
1100 frame->crop_top = 0;
1101 frame->crop_bottom = 0;
1114 static int videotoolbox_hevc_decode_params(
AVCodecContext *avctx,
1159 static int videotoolbox_prores_start_frame(
AVCodecContext *avctx,
1167 static int videotoolbox_prores_decode_slice(
AVCodecContext *avctx,
1195 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
1200 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
1202 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
1209 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
1211 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
1218 #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
1234 if (cv_pix_fmt_type == 0) {
1235 cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1237 ret->cv_pix_fmt_type = cv_pix_fmt_type;
1255 return videotoolbox_start(avctx);
1259 "Either hw_frames_ctx or hw_device_ctx must be set.\n");
1280 hw_frames->
sw_format = videotoolbox_best_pixel_format(avctx);
1283 hw_ctx = hw_frames->
hwctx;
1306 "Failed to map underlying FFmpeg pixel format %s (%s range) to "
1307 "a VideoToolbox format!\n",
1308 attempted_format ? attempted_format->
name :
"<unknown>",
1314 err = videotoolbox_start(avctx);
1333 frames_ctx->
sw_format = videotoolbox_best_pixel_format(avctx);
1339 .
p.
name =
"h263_videotoolbox",
1344 .start_frame = videotoolbox_mpeg_start_frame,
1345 .decode_slice = videotoolbox_mpeg_decode_slice,
1346 .end_frame = videotoolbox_mpeg_end_frame,
1354 .
p.
name =
"hevc_videotoolbox",
1359 .start_frame = videotoolbox_hevc_start_frame,
1360 .decode_slice = videotoolbox_hevc_decode_slice,
1361 .decode_params = videotoolbox_hevc_decode_params,
1362 .end_frame = videotoolbox_hevc_end_frame,
1370 .
p.
name =
"h264_videotoolbox",
1378 .end_frame = videotoolbox_h264_end_frame,
1386 .
p.
name =
"mpeg1_videotoolbox",
1391 .start_frame = videotoolbox_mpeg_start_frame,
1392 .decode_slice = videotoolbox_mpeg_decode_slice,
1393 .end_frame = videotoolbox_mpeg_end_frame,
1401 .
p.
name =
"mpeg2_videotoolbox",
1406 .start_frame = videotoolbox_mpeg_start_frame,
1407 .decode_slice = videotoolbox_mpeg_decode_slice,
1408 .end_frame = videotoolbox_mpeg_end_frame,
1416 .
p.
name =
"mpeg4_videotoolbox",
1421 .start_frame = videotoolbox_mpeg_start_frame,
1422 .decode_slice = videotoolbox_mpeg_decode_slice,
1423 .end_frame = videotoolbox_mpeg_end_frame,
1431 .
p.
name =
"prores_videotoolbox",
1436 .start_frame = videotoolbox_prores_start_frame,
1437 .decode_slice = videotoolbox_prores_decode_slice,
1438 .end_frame = videotoolbox_prores_end_frame,