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);
96 if (
ref->hw_frames_ctx) {
99 if (!
frame->hw_frames_ctx)
136 #define AV_W8(p, v) *(p) = (v)
144 int vt_extradata_size = 6 + 2 +
h->ps.sps->data_size + 3 +
h->ps.pps->data_size;
152 AV_W8(p + 1,
h->ps.sps->data[1]);
153 AV_W8(p + 2,
h->ps.sps->data[2]);
154 AV_W8(p + 3,
h->ps.sps->data[3]);
157 AV_WB16(p + 6,
h->ps.sps->data_size);
158 memcpy(p + 8,
h->ps.sps->data,
h->ps.sps->data_size);
159 p += 8 +
h->ps.sps->data_size;
161 AV_WB16(p + 1,
h->ps.pps->data_size);
162 memcpy(p + 3,
h->ps.pps->data,
h->ps.pps->data_size);
164 p += 3 +
h->ps.pps->data_size;
165 av_assert0(p - vt_extradata == vt_extradata_size);
170 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
172 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
180 int i, num_vps = 0, num_sps = 0, num_pps = 0;
189 int vt_extradata_size = 23 + 3 + 3 + 3;
192 #define COUNT_SIZE_PS(T, t) \
193 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
194 if (h->ps.t##ps_list[i]) { \
195 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
196 vt_extradata_size += 2 + lps->data_size; \
205 vt_extradata =
av_malloc(vt_extradata_size);
249 else if (
pps->entropy_coding_sync_enabled_flag &&
pps->tiles_enabled_flag)
251 else if (
pps->entropy_coding_sync_enabled_flag)
253 else if (
pps->tiles_enabled_flag)
257 AV_W8(p + 15, 0xfc | parallelismType);
263 AV_W8(p + 16,
sps->chroma_format_idc | 0xfc);
269 AV_W8(p + 17, (
sps->bit_depth - 8) | 0xfc);
275 AV_W8(p + 18, (
sps->bit_depth_chroma - 8) | 0xfc);
286 AV_W8(p + 21, 0 << 6 |
287 sps->max_sub_layers << 3 |
288 sps->temporal_id_nesting_flag << 2 |
296 #define APPEND_PS(T, t) \
303 HEVC_NAL_##T##PS & 0x3f); \
305 AV_WB16(p + 1, num_##t##ps); \
307 for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
308 if (h->ps.t##ps_list[i]) { \
309 const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
311 AV_WB16(p, lps->data_size); \
313 memcpy(p + 2, lps->data, lps->data_size); \
314 p += 2 + lps->data_size; \
322 av_assert0(p - vt_extradata == vt_extradata_size);
324 data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
336 if (
h->is_avc == 1) {
353 memcpy(vtctx->
sps,
h->ps.sps->data + 1, 3);
407 CVPixelBufferRelease(vtctx->
frame);
413 #if CONFIG_VIDEOTOOLBOX
431 CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->
frame;
432 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
434 int width = CVPixelBufferGetWidth(pixbuf);
435 int height = CVPixelBufferGetHeight(pixbuf);
449 CVPixelBufferRelease(
ref->pixbuf);
485 if (!
ref->hw_frames_ctx)
496 for (
i = 3;
i >= 0;
i--) {
501 bytestream2_put_byteu(pb,
b);
505 static CFDataRef videotoolbox_esds_extradata_create(
AVCodecContext *avctx)
519 bytestream2_put_byteu(&pb, 0);
523 bytestream2_put_byteu(&pb, 0x03);
524 videotoolbox_write_mp4_descr_length(&pb, full_size);
526 bytestream2_put_byteu(&pb, 0);
529 bytestream2_put_byteu(&pb, 0x04);
530 videotoolbox_write_mp4_descr_length(&pb, config_size);
531 bytestream2_put_byteu(&pb, 32);
532 bytestream2_put_byteu(&pb, 0x11);
538 bytestream2_put_byteu(&pb, 0x05);
544 bytestream2_put_byteu(&pb, 0x06);
545 bytestream2_put_byteu(&pb, 0x01);
546 bytestream2_put_byteu(&pb, 0x02);
550 data = CFDataCreate(kCFAllocatorDefault, rw_extradata,
s);
556 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
561 CMBlockBufferRef block_buf;
562 CMSampleBufferRef sample_buf;
567 status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
578 status = CMSampleBufferCreate(kCFAllocatorDefault,
593 CFRelease(block_buf);
598 static void videotoolbox_decoder_callback(
void *opaque,
599 void *sourceFrameRefCon,
601 VTDecodeInfoFlags
flags,
602 CVImageBufferRef image_buffer,
610 CVPixelBufferRelease(vtctx->
frame);
619 vtctx->
frame = CVPixelBufferRetain(image_buffer);
622 static OSStatus videotoolbox_session_decode_frame(
AVCodecContext *avctx)
625 CMSampleBufferRef sample_buf;
629 sample_buf = videotoolbox_sample_buffer_create(videotoolbox->
cm_fmt_desc,
636 status = VTDecompressionSessionDecodeFrame(videotoolbox->
session,
642 status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->
session);
644 CFRelease(sample_buf);
649 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType
codec_type,
650 CFDictionaryRef decoder_spec,
654 CMFormatDescriptionRef cm_fmt_desc;
657 status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
670 static CFDictionaryRef videotoolbox_buffer_attributes_create(
int width,
674 CFMutableDictionaryRef buffer_attributes;
675 CFMutableDictionaryRef io_surface_properties;
676 CFNumberRef cv_pix_fmt;
680 w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
width);
681 h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
height);
682 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &
pix_fmt);
684 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
686 &kCFTypeDictionaryKeyCallBacks,
687 &kCFTypeDictionaryValueCallBacks);
688 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
690 &kCFTypeDictionaryKeyCallBacks,
691 &kCFTypeDictionaryValueCallBacks);
694 CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
695 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
696 CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey,
w);
697 CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey,
h);
699 CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
701 CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
704 CFRelease(io_surface_properties);
705 CFRelease(cv_pix_fmt);
709 return buffer_attributes;
712 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType
codec_type,
715 CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
717 &kCFTypeDictionaryKeyCallBacks,
718 &kCFTypeDictionaryValueCallBacks);
720 CFDictionarySetValue(config_info,
726 CFMutableDictionaryRef avc_info;
729 avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
731 &kCFTypeDictionaryKeyCallBacks,
732 &kCFTypeDictionaryValueCallBacks);
735 case kCMVideoCodecType_MPEG4Video :
737 data = videotoolbox_esds_extradata_create(avctx);
739 CFDictionarySetValue(avc_info, CFSTR(
"esds"),
data);
741 case kCMVideoCodecType_H264 :
744 CFDictionarySetValue(avc_info, CFSTR(
"avcC"),
data);
749 CFDictionarySetValue(avc_info, CFSTR(
"hvcC"),
data);
755 CFDictionarySetValue(config_info,
756 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
770 VTDecompressionOutputCallbackRecord decoder_cb;
771 CFDictionaryRef decoder_spec;
772 CFDictionaryRef buf_attr;
802 decoder_spec = videotoolbox_decoder_config_create(videotoolbox->
cm_codec_type, avctx);
815 CFRelease(decoder_spec);
821 buf_attr = videotoolbox_buffer_attributes_create(avctx->
width,
825 decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
826 decoder_cb.decompressionOutputRefCon = avctx;
836 CFRelease(decoder_spec);
841 case kVTVideoDecoderNotAvailableNowErr:
844 case kVTVideoDecoderUnsupportedDataFormatErr:
847 case kVTCouldNotFindVideoDecoderErr:
850 case kVTVideoDecoderMalfunctionErr:
853 case kVTVideoDecoderBadDataErr:
876 VTDecompressionSessionInvalidate(videotoolbox->
session);
877 CFRelease(videotoolbox->
session);
882 static const char *videotoolbox_error_string(OSStatus
status)
885 case kVTVideoDecoderBadDataErr:
887 case kVTVideoDecoderMalfunctionErr:
888 return "decoder malfunction";
889 case kVTInvalidSessionErr:
890 return "invalid session";
901 frame->crop_right = 0;
902 frame->crop_left = 0;
904 frame->crop_bottom = 0;
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);
1095 err = videotoolbox_start(avctx);
1114 frames_ctx->
sw_format = videotoolbox_best_pixel_format(avctx);
1120 .
name =
"h263_videotoolbox",
1125 .start_frame = videotoolbox_mpeg_start_frame,
1126 .decode_slice = videotoolbox_mpeg_decode_slice,
1127 .end_frame = videotoolbox_mpeg_end_frame,
1128 .frame_params = videotoolbox_frame_params,
1129 .init = videotoolbox_common_init,
1135 .
name =
"hevc_videotoolbox",
1140 .start_frame = videotoolbox_hevc_start_frame,
1141 .decode_slice = videotoolbox_hevc_decode_slice,
1142 .decode_params = videotoolbox_hevc_decode_params,
1143 .end_frame = videotoolbox_hevc_end_frame,
1144 .frame_params = videotoolbox_frame_params,
1145 .init = videotoolbox_common_init,
1151 .
name =
"h264_videotoolbox",
1159 .end_frame = videotoolbox_h264_end_frame,
1160 .frame_params = videotoolbox_frame_params,
1161 .init = videotoolbox_common_init,
1167 .
name =
"mpeg1_videotoolbox",
1172 .start_frame = videotoolbox_mpeg_start_frame,
1173 .decode_slice = videotoolbox_mpeg_decode_slice,
1174 .end_frame = videotoolbox_mpeg_end_frame,
1175 .frame_params = videotoolbox_frame_params,
1176 .init = videotoolbox_common_init,
1182 .
name =
"mpeg2_videotoolbox",
1187 .start_frame = videotoolbox_mpeg_start_frame,
1188 .decode_slice = videotoolbox_mpeg_decode_slice,
1189 .end_frame = videotoolbox_mpeg_end_frame,
1190 .frame_params = videotoolbox_frame_params,
1191 .init = videotoolbox_common_init,
1197 .
name =
"mpeg4_videotoolbox",
1202 .start_frame = videotoolbox_mpeg_start_frame,
1203 .decode_slice = videotoolbox_mpeg_decode_slice,
1204 .end_frame = videotoolbox_mpeg_end_frame,
1205 .frame_params = videotoolbox_frame_params,
1206 .init = videotoolbox_common_init,
1216 ret->output_callback = videotoolbox_decoder_callback;
1219 if (cv_pix_fmt_type == 0) {
1220 cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1222 ret->cv_pix_fmt_type = cv_pix_fmt_type;
1240 avctx->
hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(videotoolbox_best_pixel_format(avctx));
1243 return videotoolbox_start(avctx);
1249 videotoolbox_stop(avctx);