35 #include <TargetConditionals.h>
37 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
38 # define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
40 #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
41 # define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
44 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
48 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
59 CVPixelBufferRelease(
ref->pixbuf);
94 frame->crop_right = 0;
97 frame->crop_bottom = 0;
101 if (
ref->hw_frames_ctx) {
104 if (!
frame->hw_frames_ctx)
141 #define AV_W8(p, v) *(p) = (v)
149 int vt_extradata_size = 6 + 2 +
h->ps.sps->data_size + 3 +
h->ps.pps->data_size;
157 AV_W8(p + 1,
h->ps.sps->data[1]);
158 AV_W8(p + 2,
h->ps.sps->data[2]);
159 AV_W8(p + 3,
h->ps.sps->data[3]);
162 AV_WB16(p + 6,
h->ps.sps->data_size);
163 memcpy(p + 8,
h->ps.sps->data,
h->ps.sps->data_size);
164 p += 8 +
h->ps.sps->data_size;
166 AV_WB16(p + 1,
h->ps.pps->data_size);
167 memcpy(p + 3,
h->ps.pps->data,
h->ps.pps->data_size);
169 p += 3 +
h->ps.pps->data_size;
170 av_assert0(p - vt_extradata == vt_extradata_size);
175 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
177 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
185 int i, num_vps = 0, num_sps = 0, num_pps = 0;
194 int vt_extradata_size = 23 + 3 + 3 + 3;
197 #define COUNT_SIZE_PS(T, t) \
198 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
199 if (h->ps.t##ps_list[i]) { \
200 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
201 vt_extradata_size += 2 + lps->data_size; \
210 vt_extradata =
av_malloc(vt_extradata_size);
254 else if (
pps->entropy_coding_sync_enabled_flag &&
pps->tiles_enabled_flag)
256 else if (
pps->entropy_coding_sync_enabled_flag)
258 else if (
pps->tiles_enabled_flag)
262 AV_W8(p + 15, 0xfc | parallelismType);
268 AV_W8(p + 16,
sps->chroma_format_idc | 0xfc);
274 AV_W8(p + 17, (
sps->bit_depth - 8) | 0xfc);
280 AV_W8(p + 18, (
sps->bit_depth_chroma - 8) | 0xfc);
291 AV_W8(p + 21, 0 << 6 |
292 sps->max_sub_layers << 3 |
293 sps->temporal_id_nesting_flag << 2 |
301 #define APPEND_PS(T, t) \
308 HEVC_NAL_##T##PS & 0x3f); \
310 AV_WB16(p + 1, num_##t##ps); \
312 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
313 if (h->ps.t##ps_list[i]) { \
314 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
316 AV_WB16(p, lps->data_size); \
318 memcpy(p + 2, lps->data, lps->data_size); \
319 p += 2 + lps->data_size; \
327 av_assert0(p - vt_extradata == vt_extradata_size);
329 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
341 if (
h->is_avc == 1) {
358 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
412 CVPixelBufferRelease(vtctx->
frame);
418 #if CONFIG_VIDEOTOOLBOX
436 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->
frame;
437 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
439 int width = CVPixelBufferGetWidth(pixbuf);
440 int height = CVPixelBufferGetHeight(pixbuf);
454 CVPixelBufferRelease(
ref->pixbuf);
490 if (!
ref->hw_frames_ctx)
496 static void videotoolbox_write_mp4_descr_length(
PutByteContext *pb,
int length)
501 for (
i = 3;
i >= 0;
i--) {
502 b = (length >> (
i * 7)) & 0x7F;
506 bytestream2_put_byteu(pb,
b);
510 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
524 bytestream2_put_byteu(&pb, 0);
528 bytestream2_put_byteu(&pb, 0x03);
529 videotoolbox_write_mp4_descr_length(&pb, full_size);
531 bytestream2_put_byteu(&pb, 0);
534 bytestream2_put_byteu(&pb, 0x04);
535 videotoolbox_write_mp4_descr_length(&pb, config_size);
536 bytestream2_put_byteu(&pb, 32);
537 bytestream2_put_byteu(&pb, 0x11);
543 bytestream2_put_byteu(&pb, 0x05);
549 bytestream2_put_byteu(&pb, 0x06);
550 bytestream2_put_byteu(&pb, 0x01);
551 bytestream2_put_byteu(&pb, 0x02);
555 data = CFDataCreate(kCFAllocatorDefault, rw_extradata,
s);
561 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
566 CMBlockBufferRef block_buf;
567 CMSampleBufferRef sample_buf;
572 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
583 status = CMSampleBufferCreate(kCFAllocatorDefault,
598 CFRelease(block_buf);
603 static void videotoolbox_decoder_callback(
void *opaque,
604 void *sourceFrameRefCon,
606 VTDecodeInfoFlags
flags,
607 CVImageBufferRef image_buffer,
615 CVPixelBufferRelease(vtctx->
frame);
624 vtctx->
frame = CVPixelBufferRetain(image_buffer);
627 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
630 CMSampleBufferRef sample_buf;
634 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
641 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
647 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
649 CFRelease(sample_buf);
654 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType
codec_type,
655 CFDictionaryRef decoder_spec,
659 CMFormatDescriptionRef cm_fmt_desc;
662 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
675 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
679 CFMutableDictionaryRef buffer_attributes;
680 CFMutableDictionaryRef io_surface_properties;
681 CFNumberRef cv_pix_fmt;
685 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
width);
686 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
height);
687 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
pix_fmt);
689 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
691 &kCFTypeDictionaryKeyCallBacks,
692 &kCFTypeDictionaryValueCallBacks);
693 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
695 &kCFTypeDictionaryKeyCallBacks,
696 &kCFTypeDictionaryValueCallBacks);
699 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
700 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
701 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey,
w);
702 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey,
h);
704 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
706 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
709 CFRelease(io_surface_properties);
710 CFRelease(cv_pix_fmt);
714 return buffer_attributes;
717 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
720 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
722 &kCFTypeDictionaryKeyCallBacks,
723 &kCFTypeDictionaryValueCallBacks);
725 CFDictionarySetValue(config_info,
731 CFMutableDictionaryRef avc_info;
734 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
736 &kCFTypeDictionaryKeyCallBacks,
737 &kCFTypeDictionaryValueCallBacks);
740 case kCMVideoCodecType_MPEG4Video :
742 data = videotoolbox_esds_extradata_create(avctx);
744 CFDictionarySetValue(avc_info, CFSTR(
"esds"),
data);
746 case kCMVideoCodecType_H264 :
749 CFDictionarySetValue(avc_info, CFSTR(
"avcC"),
data);
754 CFDictionarySetValue(avc_info, CFSTR(
"hvcC"),
data);
760 CFDictionarySetValue(config_info,
761 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
775 VTDecompressionOutputCallbackRecord decoder_cb;
776 CFDictionaryRef decoder_spec;
777 CFDictionaryRef buf_attr;
807 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
820 CFRelease(decoder_spec);
826 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
830 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
831 decoder_cb.decompressionOutputRefCon = avctx;
841 CFRelease(decoder_spec);
846 case kVTVideoDecoderNotAvailableNowErr:
849 case kVTVideoDecoderUnsupportedDataFormatErr:
852 case kVTCouldNotFindVideoDecoderErr:
855 case kVTVideoDecoderMalfunctionErr:
858 case kVTVideoDecoderBadDataErr:
881 VTDecompressionSessionInvalidate(videotoolbox->
session);
882 CFRelease(videotoolbox->
session);
887 static const char *videotoolbox_error_string(OSStatus
status)
890 case kVTVideoDecoderBadDataErr:
892 case kVTVideoDecoderMalfunctionErr:
893 return "decoder malfunction";
894 case kVTInvalidSessionErr:
895 return "invalid session";
909 videotoolbox_stop(avctx);
910 if (videotoolbox_start(avctx) != 0) {
918 status = videotoolbox_session_decode_frame(avctx);
920 if (
status == kVTVideoDecoderMalfunctionErr ||
status == kVTInvalidSessionErr)
931 return videotoolbox_buffer_create(avctx,
frame);
939 int ret = videotoolbox_common_end_frame(avctx,
frame);
973 h->output_frame->crop_right = 0;
974 h->output_frame->crop_left = 0;
975 h->output_frame->crop_top = 0;
976 h->output_frame->crop_bottom = 0;
978 int ret = videotoolbox_common_end_frame(avctx,
frame);
1004 return videotoolbox_common_end_frame(avctx,
frame);
1016 videotoolbox_stop(avctx);
1049 "Either hw_frames_ctx or hw_device_ctx must be set.\n");
1070 hw_frames->
sw_format = videotoolbox_best_pixel_format(avctx);
1094 "Failed to map underlying FFmpeg pixel format %s (%s range) to "
1095 "a VideoToolbox format!\n",
1096 attempted_format ? attempted_format->
name :
"<unknown>",
1102 err = videotoolbox_start(avctx);
1121 frames_ctx->
sw_format = videotoolbox_best_pixel_format(avctx);
1127 .
name =
"h263_videotoolbox",
1132 .start_frame = videotoolbox_mpeg_start_frame,
1133 .decode_slice = videotoolbox_mpeg_decode_slice,
1134 .end_frame = videotoolbox_mpeg_end_frame,
1135 .frame_params = videotoolbox_frame_params,
1136 .init = videotoolbox_common_init,
1142 .
name =
"hevc_videotoolbox",
1147 .start_frame = videotoolbox_hevc_start_frame,
1148 .decode_slice = videotoolbox_hevc_decode_slice,
1149 .decode_params = videotoolbox_hevc_decode_params,
1150 .end_frame = videotoolbox_hevc_end_frame,
1151 .frame_params = videotoolbox_frame_params,
1152 .init = videotoolbox_common_init,
1158 .
name =
"h264_videotoolbox",
1166 .end_frame = videotoolbox_h264_end_frame,
1167 .frame_params = videotoolbox_frame_params,
1168 .init = videotoolbox_common_init,
1174 .
name =
"mpeg1_videotoolbox",
1179 .start_frame = videotoolbox_mpeg_start_frame,
1180 .decode_slice = videotoolbox_mpeg_decode_slice,
1181 .end_frame = videotoolbox_mpeg_end_frame,
1182 .frame_params = videotoolbox_frame_params,
1183 .init = videotoolbox_common_init,
1189 .
name =
"mpeg2_videotoolbox",
1194 .start_frame = videotoolbox_mpeg_start_frame,
1195 .decode_slice = videotoolbox_mpeg_decode_slice,
1196 .end_frame = videotoolbox_mpeg_end_frame,
1197 .frame_params = videotoolbox_frame_params,
1198 .init = videotoolbox_common_init,
1204 .
name =
"mpeg4_videotoolbox",
1209 .start_frame = videotoolbox_mpeg_start_frame,
1210 .decode_slice = videotoolbox_mpeg_decode_slice,
1211 .end_frame = videotoolbox_mpeg_end_frame,
1212 .frame_params = videotoolbox_frame_params,
1213 .init = videotoolbox_common_init,
1224 ret->output_callback = videotoolbox_decoder_callback;
1227 if (cv_pix_fmt_type == 0) {
1228 cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1230 ret->cv_pix_fmt_type = cv_pix_fmt_type;
1238 return av_videotoolbox_alloc_context_with_pix_fmt(
AV_PIX_FMT_NONE,
false);
1253 return videotoolbox_start(avctx);
1259 videotoolbox_stop(avctx);