36 #include <Availability.h>
37 #include <AvailabilityMacros.h>
38 #include <TargetConditionals.h>
40 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
41 # define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
43 #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
44 # define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
47 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
51 #if !HAVE_KCMVIDEOCODECTYPE_VP9
55 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
66 CVPixelBufferRelease(
ref->pixbuf);
102 frame->crop_right = 0;
103 frame->crop_left = 0;
105 frame->crop_bottom = 0;
110 frame->data[3] = (uint8_t*)
ref->pixbuf;
112 if (
ref->hw_frames_ctx) {
115 if (!
frame->hw_frames_ctx)
152 #define AV_W8(p, v) *(p) = (v)
160 for (
i = 0;
i < src_size;
i++) {
161 if (
i + 2 < src_size &&
163 src[
i + 1] == 0x00 &&
164 src[
i + 2] <= 0x03) {
192 int vt_extradata_size;
193 uint8_t *vt_extradata;
195 vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size;
196 vt_extradata =
av_malloc(vt_extradata_size);
204 AV_W8(p + 1,
h->ps.sps->data[1]);
205 AV_W8(p + 2,
h->ps.sps->data[2]);
206 AV_W8(p + 3,
h->ps.sps->data[3]);
211 p +=
escape_ps(p,
h->ps.sps->data,
h->ps.sps->data_size);
215 p +=
escape_ps(p,
h->ps.pps->data,
h->ps.pps->data_size);
217 av_assert0(p - vt_extradata == vt_extradata_size);
222 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
224 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
232 int i, num_vps = 0, num_sps = 0, num_pps = 0;
238 uint8_t parallelismType;
241 int vt_extradata_size = 23 + 3 + 3 + 3;
242 uint8_t *vt_extradata;
244 #define COUNT_SIZE_PS(T, t) \
245 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
246 if (h->ps.t##ps_list[i]) { \
247 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
248 vt_extradata_size += 2 + lps->data_size; \
257 vt_extradata =
av_malloc(vt_extradata_size);
301 else if (
pps->entropy_coding_sync_enabled_flag &&
pps->tiles_enabled_flag)
303 else if (
pps->entropy_coding_sync_enabled_flag)
305 else if (
pps->tiles_enabled_flag)
309 AV_W8(p + 15, 0xfc | parallelismType);
315 AV_W8(p + 16,
sps->chroma_format_idc | 0xfc);
321 AV_W8(p + 17, (
sps->bit_depth - 8) | 0xfc);
327 AV_W8(p + 18, (
sps->bit_depth_chroma - 8) | 0xfc);
338 AV_W8(p + 21, 0 << 6 |
339 sps->max_sub_layers << 3 |
340 sps->temporal_id_nesting_flag << 2 |
348 #define APPEND_PS(T, t) \
355 HEVC_NAL_##T##PS & 0x3f); \
357 AV_WB16(p + 1, num_##t##ps); \
359 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
360 if (h->ps.t##ps_list[i]) { \
361 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
363 AV_WB16(p, lps->data_size); \
365 memcpy(p + 2, lps->data, lps->data_size); \
366 p += 2 + lps->data_size; \
374 av_assert0(p - vt_extradata == vt_extradata_size);
376 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
388 if (
h->is_avc == 1) {
405 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
453 #if CONFIG_VIDEOTOOLBOX
480 VTDecompressionSessionInvalidate(videotoolbox->
session);
481 CFRelease(videotoolbox->
session);
494 CVPixelBufferRelease(vtctx->
frame);
497 videotoolbox_stop(avctx);
508 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->
frame;
509 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
511 int width = CVPixelBufferGetWidth(pixbuf);
512 int height = CVPixelBufferGetHeight(pixbuf);
526 CVPixelBufferRelease(
ref->pixbuf);
562 if (!
ref->hw_frames_ctx)
568 static void videotoolbox_write_mp4_descr_length(
PutByteContext *pb,
int length)
573 for (
i = 3;
i >= 0;
i--) {
574 b = (length >> (
i * 7)) & 0x7F;
578 bytestream2_put_byteu(pb,
b);
582 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
585 uint8_t *rw_extradata;
596 bytestream2_put_byteu(&pb, 0);
600 bytestream2_put_byteu(&pb, 0x03);
601 videotoolbox_write_mp4_descr_length(&pb, full_size);
603 bytestream2_put_byteu(&pb, 0);
606 bytestream2_put_byteu(&pb, 0x04);
607 videotoolbox_write_mp4_descr_length(&pb, config_size);
608 bytestream2_put_byteu(&pb, 32);
609 bytestream2_put_byteu(&pb, 0x11);
615 bytestream2_put_byteu(&pb, 0x05);
621 bytestream2_put_byteu(&pb, 0x06);
622 bytestream2_put_byteu(&pb, 0x01);
623 bytestream2_put_byteu(&pb, 0x02);
627 data = CFDataCreate(kCFAllocatorDefault, rw_extradata,
s);
633 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
638 CMBlockBufferRef block_buf;
639 CMSampleBufferRef sample_buf;
644 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
655 status = CMSampleBufferCreate(kCFAllocatorDefault,
670 CFRelease(block_buf);
675 static void videotoolbox_decoder_callback(
void *opaque,
676 void *sourceFrameRefCon,
678 VTDecodeInfoFlags
flags,
679 CVImageBufferRef image_buffer,
687 CVPixelBufferRelease(vtctx->
frame);
696 vtctx->
frame = CVPixelBufferRetain(image_buffer);
699 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
702 CMSampleBufferRef sample_buf;
706 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
713 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
719 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
721 CFRelease(sample_buf);
726 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType
codec_type,
727 CFDictionaryRef decoder_spec,
731 CMFormatDescriptionRef cm_fmt_desc;
734 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
747 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
751 CFMutableDictionaryRef buffer_attributes;
752 CFMutableDictionaryRef io_surface_properties;
753 CFNumberRef cv_pix_fmt;
757 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
width);
758 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
height);
759 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
pix_fmt);
761 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
763 &kCFTypeDictionaryKeyCallBacks,
764 &kCFTypeDictionaryValueCallBacks);
765 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
767 &kCFTypeDictionaryKeyCallBacks,
768 &kCFTypeDictionaryValueCallBacks);
771 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
772 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
773 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey,
w);
774 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey,
h);
776 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
778 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
781 CFRelease(io_surface_properties);
782 CFRelease(cv_pix_fmt);
786 return buffer_attributes;
789 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
792 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
794 &kCFTypeDictionaryKeyCallBacks,
795 &kCFTypeDictionaryValueCallBacks);
797 CFDictionarySetValue(config_info,
803 CFMutableDictionaryRef avc_info;
806 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
808 &kCFTypeDictionaryKeyCallBacks,
809 &kCFTypeDictionaryValueCallBacks);
812 case kCMVideoCodecType_MPEG4Video :
814 data = videotoolbox_esds_extradata_create(avctx);
816 CFDictionarySetValue(avc_info, CFSTR(
"esds"),
data);
818 case kCMVideoCodecType_H264 :
821 CFDictionarySetValue(avc_info, CFSTR(
"avcC"),
data);
826 CFDictionarySetValue(avc_info, CFSTR(
"hvcC"),
data);
828 #if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL
832 CFDictionarySetValue(avc_info, CFSTR(
"vpcC"),
data);
839 CFDictionarySetValue(config_info,
840 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
854 VTDecompressionOutputCallbackRecord decoder_cb;
855 CFDictionaryRef decoder_spec;
856 CFDictionaryRef buf_attr;
887 case MKTAG(
'a',
'p',
'c',
'o'):
888 case
MKTAG(
'a',
'p',
'c',
's'):
889 case
MKTAG(
'a',
'p',
'c',
'n'):
890 case
MKTAG(
'a',
'p',
'c',
'h'):
891 case
MKTAG(
'a',
'p',
'4',
'h'):
892 case
MKTAG(
'a',
'p',
'4',
'x'):
893 videotoolbox->cm_codec_type =
av_bswap32(avctx->codec_tag);
904 #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)
906 if (__builtin_available(macOS 10.9, *)) {
907 VTRegisterProfessionalVideoWorkflowVideoDecoders();
912 #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)
913 if (__builtin_available(macOS 11.0, *)) {
914 VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->
cm_codec_type);
918 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
931 CFRelease(decoder_spec);
937 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
941 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
942 decoder_cb.decompressionOutputRefCon = avctx;
952 CFRelease(decoder_spec);
957 case kVTVideoDecoderNotAvailableNowErr:
960 case kVTVideoDecoderUnsupportedDataFormatErr:
963 case kVTCouldNotFindVideoDecoderErr:
966 case kVTVideoDecoderMalfunctionErr:
969 case kVTVideoDecoderBadDataErr:
980 static const char *videotoolbox_error_string(OSStatus
status)
983 case kVTVideoDecoderBadDataErr:
985 case kVTVideoDecoderMalfunctionErr:
986 return "decoder malfunction";
987 case kVTInvalidSessionErr:
988 return "invalid session";
1002 videotoolbox_stop(avctx);
1003 if (videotoolbox_start(avctx) != 0) {
1011 status = videotoolbox_session_decode_frame(avctx);
1013 if (
status == kVTVideoDecoderMalfunctionErr ||
status == kVTInvalidSessionErr)
1019 if (!vtctx->
frame) {
1024 return videotoolbox_buffer_create(avctx,
frame);
1052 static int videotoolbox_hevc_decode_params(
AVCodecContext *avctx,
1066 h->output_frame->crop_right = 0;
1067 h->output_frame->crop_left = 0;
1068 h->output_frame->crop_top = 0;
1069 h->output_frame->crop_bottom = 0;
1100 static int videotoolbox_prores_start_frame(
AVCodecContext *avctx,
1107 static int videotoolbox_prores_decode_slice(
AVCodecContext *avctx,
1134 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
1139 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
1141 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
1148 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
1150 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
1157 #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
1178 "Either hw_frames_ctx or hw_device_ctx must be set.\n");
1199 hw_frames->
sw_format = videotoolbox_best_pixel_format(avctx);
1223 "Failed to map underlying FFmpeg pixel format %s (%s range) to "
1224 "a VideoToolbox format!\n",
1225 attempted_format ? attempted_format->
name :
"<unknown>",
1231 err = videotoolbox_start(avctx);
1250 frames_ctx->
sw_format = videotoolbox_best_pixel_format(avctx);
1256 .
name =
"h263_videotoolbox",
1261 .start_frame = videotoolbox_mpeg_start_frame,
1262 .decode_slice = videotoolbox_mpeg_decode_slice,
1263 .end_frame = videotoolbox_mpeg_end_frame,
1271 .
name =
"hevc_videotoolbox",
1276 .start_frame = videotoolbox_hevc_start_frame,
1277 .decode_slice = videotoolbox_hevc_decode_slice,
1278 .decode_params = videotoolbox_hevc_decode_params,
1279 .end_frame = videotoolbox_hevc_end_frame,
1287 .
name =
"h264_videotoolbox",
1295 .end_frame = videotoolbox_h264_end_frame,
1303 .
name =
"mpeg1_videotoolbox",
1308 .start_frame = videotoolbox_mpeg_start_frame,
1309 .decode_slice = videotoolbox_mpeg_decode_slice,
1310 .end_frame = videotoolbox_mpeg_end_frame,
1318 .
name =
"mpeg2_videotoolbox",
1323 .start_frame = videotoolbox_mpeg_start_frame,
1324 .decode_slice = videotoolbox_mpeg_decode_slice,
1325 .end_frame = videotoolbox_mpeg_end_frame,
1333 .
name =
"mpeg4_videotoolbox",
1338 .start_frame = videotoolbox_mpeg_start_frame,
1339 .decode_slice = videotoolbox_mpeg_decode_slice,
1340 .end_frame = videotoolbox_mpeg_end_frame,
1348 .
name =
"prores_videotoolbox",
1353 .start_frame = videotoolbox_prores_start_frame,
1354 .decode_slice = videotoolbox_prores_decode_slice,
1355 .end_frame = videotoolbox_prores_end_frame,
1368 ret->output_callback = videotoolbox_decoder_callback;
1371 if (cv_pix_fmt_type == 0) {
1372 cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1374 ret->cv_pix_fmt_type = cv_pix_fmt_type;
1382 return av_videotoolbox_alloc_context_with_pix_fmt(
AV_PIX_FMT_NONE,
false);
1397 return videotoolbox_start(avctx);
1403 videotoolbox_stop(avctx);