21 #include <VideoToolbox/VideoToolbox.h>
22 #include <CoreVideo/CoreVideo.h>
23 #include <CoreMedia/CoreMedia.h>
24 #include <TargetConditionals.h>
25 #include <Availability.h>
43 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
47 #if !HAVE_KCMVIDEOCODECTYPE_HEVCWITHALPHA
51 #if !HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
56 #ifndef TARGET_CPU_ARM64
57 # define TARGET_CPU_ARM64 0
61 size_t parameterSetIndex,
62 const uint8_t **parameterSetPointerOut,
63 size_t *parameterSetSizeOut,
64 size_t *parameterSetCountOut,
65 int *NALUnitHeaderLengthOut);
136 #define GET_SYM(symbol, defaultVal) \
138 CFStringRef* handle = (CFStringRef*)dlsym(RTLD_DEFAULT, #symbol); \
140 compat_keys.symbol = CFSTR(defaultVal); \
142 compat_keys.symbol = *handle; \
148 compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex =
151 "CMVideoFormatDescriptionGetHEVCParameterSetAtIndex"
191 "TargetQualityForAlpha");
193 "PrioritizeEncodingSpeedOverQuality");
198 "EnableHardwareAcceleratedVideoEncoder");
200 "RequireHardwareAcceleratedVideoEncoder");
202 "EnableLowLatencyRateControl");
205 "MaximizePowerEfficiency");
207 "ReferenceBufferCount");
212 #define H264_PROFILE_CONSTRAINED_HIGH (AV_PROFILE_H264_HIGH | AV_PROFILE_H264_CONSTRAINED)
286 CFStringRef encoder_id =
NULL;
288 CFIndex length, max_size;
299 length = CFStringGetLength(encoder_id);
300 max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
303 CFRelease(encoder_id);
307 CFStringGetCString(encoder_id,
310 kCFStringEncodingUTF8);
313 CFRelease(encoder_id);
320 CFStringRef profile_level,
321 CFNumberRef gamma_level,
322 CFDictionaryRef enc_info,
323 CFDictionaryRef pixel_buffer_info);
350 CFRelease(
info->cm_buffer);
428 *buf =
info->cm_buffer;
431 }
else if (
info->sei) {
469 CMSampleBufferRef sample_buffer,
476 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
477 CMBlockBufferRef
block = CMSampleBufferGetDataBuffer(sample_buffer);
479 if (length_code_size > 4)
482 while (
offset < src_size) {
492 if (
status != kCMBlockBufferNoErr) {
496 for (
i = 0;
i < length_code_size;
i++) {
498 box_len |= size_buf[
i];
501 curr_src_len = box_len + length_code_size;
513 double alpha_quality)
526 return MKBETAG(
'a',
'p',
'c',
'o');
528 return MKBETAG(
'a',
'p',
'c',
's');
530 return MKBETAG(
'a',
'p',
'c',
'n');
532 return MKBETAG(
'a',
'p',
'c',
'h');
534 return MKBETAG(
'a',
'p',
'4',
'h');
536 return MKBETAG(
'a',
'p',
'4',
'x');
543 desc->log2_chroma_w == 0))
544 return MKBETAG(
'a',
'p',
'4',
'h');
546 return MKBETAG(
'a',
'p',
'c',
'n');
562 CMVideoFormatDescriptionRef vid_fmt,
566 size_t total_size = 0;
568 int is_count_bad = 0;
583 for (
i = 0;
i < ps_count || is_count_bad;
i++) {
597 if (
i > 0 && is_count_bad)
status = 0;
616 CMVideoFormatDescriptionRef vid_fmt,
622 int is_count_bad = 0;
640 for (
i = 0;
i < ps_count || is_count_bad;
i++) {
652 if (
i > 0 && is_count_bad)
status = 0;
658 if (dst_size < next_offset) {
666 memcpy(dst +
offset, ps, ps_size);
681 CMVideoFormatDescriptionRef vid_fmt;
685 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
711 CFDataRef
data = CMFormatDescriptionGetExtension(vid_fmt, kCMFormatDescriptionExtension_VerbatimSampleDescription);
712 if (
data && CFGetTypeID(
data) == CFDataGetTypeID()) {
713 CFIndex
size = CFDataGetLength(
data);
729 void *sourceFrameCtx,
731 VTEncodeInfoFlags
flags,
732 CMSampleBufferRef sample_buffer)
748 if (!sample_buffer) {
765 CMSampleBufferRef sample_buffer,
769 CMVideoFormatDescriptionRef vid_fmt;
773 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
801 CFStringRef *profile_level_val)
811 *profile_level_val =
NULL;
818 switch (vtctx->
level) {
819 case 0: *profile_level_val =
820 compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel;
break;
821 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3;
break;
822 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0;
break;
823 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1;
break;
824 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2;
break;
825 case 40: *profile_level_val =
826 compat_keys.kVTProfileLevel_H264_Baseline_4_0;
break;
827 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1;
break;
828 case 42: *profile_level_val =
829 compat_keys.kVTProfileLevel_H264_Baseline_4_2;
break;
830 case 50: *profile_level_val =
831 compat_keys.kVTProfileLevel_H264_Baseline_5_0;
break;
832 case 51: *profile_level_val =
833 compat_keys.kVTProfileLevel_H264_Baseline_5_1;
break;
834 case 52: *profile_level_val =
835 compat_keys.kVTProfileLevel_H264_Baseline_5_2;
break;
840 *profile_level_val =
compat_keys.kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel;
842 if (vtctx->
level != 0) {
845 "Level is auto-selected when constrained-baseline "
846 "profile is used. The output may be encoded with a "
847 "different level.\n");
852 switch (vtctx->
level) {
853 case 0: *profile_level_val =
854 compat_keys.kVTProfileLevel_H264_Main_AutoLevel;
break;
855 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0;
break;
856 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1;
break;
857 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2;
break;
858 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0;
break;
859 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1;
break;
860 case 42: *profile_level_val =
862 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0;
break;
863 case 51: *profile_level_val =
865 case 52: *profile_level_val =
871 *profile_level_val =
compat_keys.kVTProfileLevel_H264_ConstrainedHigh_AutoLevel;
873 if (vtctx->
level != 0) {
876 "Level is auto-selected when constrained-high profile "
877 "is used. The output may be encoded with a different "
883 switch (vtctx->
level) {
884 case 0: *profile_level_val =
885 compat_keys.kVTProfileLevel_H264_High_AutoLevel;
break;
886 case 30: *profile_level_val =
888 case 31: *profile_level_val =
890 case 32: *profile_level_val =
892 case 40: *profile_level_val =
894 case 41: *profile_level_val =
896 case 42: *profile_level_val =
898 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0;
break;
899 case 51: *profile_level_val =
901 case 52: *profile_level_val =
906 switch (vtctx->
level) {
907 case 0: *profile_level_val =
908 compat_keys.kVTProfileLevel_H264_Extended_AutoLevel;
break;
909 case 50: *profile_level_val =
910 compat_keys.kVTProfileLevel_H264_Extended_5_0;
break;
915 if (!*profile_level_val) {
930 CFStringRef *profile_level_val)
939 *profile_level_val =
NULL;
953 "main profile with %d bit input\n",
bit_depth);
960 "Invalid main10 profile with %d bit input\n",
bit_depth);
968 if (!*profile_level_val) {
979 int* av_pixel_format,
982 const char *range_name;
988 if (*av_pixel_format)
993 "Could not get pixel format for color format '%s' range '%s'.\n",
995 range_name ? range_name :
"Unknown");
1004 CFDictionarySetValue(dict,
1005 kCVImageBufferColorPrimariesKey,
1010 CFDictionarySetValue(dict,
1011 kCVImageBufferTransferFunctionKey,
1016 CFDictionarySetValue(dict,
1017 kCVImageBufferYCbCrMatrixKey,
1023 CFMutableDictionaryRef* dict)
1025 CFNumberRef cv_color_format_num =
NULL;
1026 CFNumberRef width_num =
NULL;
1027 CFNumberRef height_num =
NULL;
1028 CFMutableDictionaryRef pixel_buffer_info =
NULL;
1029 int cv_color_format;
1037 pixel_buffer_info = CFDictionaryCreateMutable(
1038 kCFAllocatorDefault,
1040 &kCFCopyStringDictionaryKeyCallBacks,
1041 &kCFTypeDictionaryValueCallBacks);
1043 if (!pixel_buffer_info)
goto pbinfo_nomem;
1045 cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
1046 kCFNumberSInt32Type,
1048 if (!cv_color_format_num)
goto pbinfo_nomem;
1050 CFDictionarySetValue(pixel_buffer_info,
1051 kCVPixelBufferPixelFormatTypeKey,
1052 cv_color_format_num);
1055 width_num = CFNumberCreate(kCFAllocatorDefault,
1056 kCFNumberSInt32Type,
1058 if (!width_num)
goto pbinfo_nomem;
1060 CFDictionarySetValue(pixel_buffer_info,
1061 kCVPixelBufferWidthKey,
1065 height_num = CFNumberCreate(kCFAllocatorDefault,
1066 kCFNumberSInt32Type,
1068 if (!height_num)
goto pbinfo_nomem;
1070 CFDictionarySetValue(pixel_buffer_info,
1071 kCVPixelBufferHeightKey,
1077 *dict = pixel_buffer_info;
1084 if (pixel_buffer_info) CFRelease(pixel_buffer_info);
1090 CFNumberRef *gamma_level)
1094 *gamma_level =
NULL;
1102 *gamma_level = CFNumberCreate(
NULL, kCFNumberFloat32Type, &gamma);
1114 const char *print_option_name,
1120 if (
status == kVTPropertyNotSupportedErr) {
1123 "This device does not support the %s option. Value ignored.\n",
1125 }
else if (
status != 0) {
1128 "Error setting %s: Error %d\n",
1136 const char* print_option_name,
1138 CFNumberRef value_cfnum = CFNumberCreate(kCFAllocatorDefault,
1142 if (value_cfnum ==
NULL) {
1148 CFRelease(value_cfnum);
1155 CFStringRef profile_level,
1156 CFNumberRef gamma_level,
1157 CFDictionaryRef enc_info,
1158 CFDictionaryRef pixel_buffer_info,
1159 bool constant_bit_rate,
1160 VTCompressionSessionRef *session)
1166 CFNumberRef bit_rate_num;
1167 CFNumberRef quality_num;
1168 CFNumberRef bytes_per_second;
1169 CFNumberRef one_second;
1170 CFArrayRef data_rate_limits;
1171 int64_t bytes_per_second_value = 0;
1172 int64_t one_second_value = 0;
1175 int status = VTCompressionSessionCreate(kCFAllocatorDefault,
1181 kCFAllocatorDefault,
1189 #if !TARGET_OS_IPHONE
1191 av_log(avctx,
AV_LOG_ERROR,
"Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
1198 #if defined (MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13)
1199 if (__builtin_available(macOS 10.13, *)) {
1200 status = VTCopySupportedPropertyDictionaryForEncoder(avctx->
width,
1219 av_log(avctx,
AV_LOG_ERROR,
"Error: -q:v qscale not available for encoder. Use -b:v bitrate instead.\n");
1225 quality_num = CFNumberCreate(kCFAllocatorDefault,
1226 kCFNumberFloat32Type,
1228 if (!quality_num)
return AVERROR(ENOMEM);
1231 kVTCompressionPropertyKey_Quality,
1233 CFRelease(quality_num);
1235 bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
1236 kCFNumberSInt32Type,
1238 if (!bit_rate_num)
return AVERROR(ENOMEM);
1240 if (constant_bit_rate) {
1242 compat_keys.kVTCompressionPropertyKey_ConstantBitRate,
1244 if (
status == kVTPropertyNotSupportedErr) {
1245 av_log(avctx,
AV_LOG_ERROR,
"Error: -constant_bit_rate true is not supported by the encoder.\n");
1250 kVTCompressionPropertyKey_AverageBitRate,
1254 CFRelease(bit_rate_num);
1264 compat_keys.kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality,
1265 vtctx->
prio_speed ? kCFBooleanTrue : kCFBooleanFalse);
1267 av_log(avctx,
AV_LOG_WARNING,
"PrioritizeEncodingSpeedOverQuality property is not supported on this device. Ignoring.\n");
1273 bytes_per_second_value = max_rate >> 3;
1274 bytes_per_second = CFNumberCreate(kCFAllocatorDefault,
1275 kCFNumberSInt64Type,
1276 &bytes_per_second_value);
1277 if (!bytes_per_second) {
1280 one_second_value = 1;
1281 one_second = CFNumberCreate(kCFAllocatorDefault,
1282 kCFNumberSInt64Type,
1285 CFRelease(bytes_per_second);
1288 nums[0] = (
void *)bytes_per_second;
1289 nums[1] = (
void *)one_second;
1290 data_rate_limits = CFArrayCreate(kCFAllocatorDefault,
1291 (
const void **)nums,
1293 &kCFTypeArrayCallBacks);
1295 if (!data_rate_limits) {
1296 CFRelease(bytes_per_second);
1297 CFRelease(one_second);
1301 kVTCompressionPropertyKey_DataRateLimits,
1304 CFRelease(bytes_per_second);
1305 CFRelease(one_second);
1306 CFRelease(data_rate_limits);
1320 CFNumberRef alpha_quality_num = CFNumberCreate(kCFAllocatorDefault,
1321 kCFNumberDoubleType,
1323 if (!alpha_quality_num)
return AVERROR(ENOMEM);
1326 compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha,
1328 CFRelease(alpha_quality_num);
1333 "Error setting alpha quality: %d\n",
1339 if (profile_level) {
1341 kVTCompressionPropertyKey_ProfileLevel,
1344 av_log(avctx,
AV_LOG_ERROR,
"Error setting profile/level property: %d. Output will be encoded using a supported profile/level combination.\n",
status);
1349 CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
1357 kVTCompressionPropertyKey_MaxKeyFrameInterval,
1359 CFRelease(interval);
1369 kVTCompressionPropertyKey_MoreFramesBeforeStart,
1372 if (
status == kVTPropertyNotSupportedErr) {
1373 av_log(avctx,
AV_LOG_WARNING,
"frames_before property is not supported on this device. Ignoring.\n");
1381 kVTCompressionPropertyKey_MoreFramesAfterEnd,
1384 if (
status == kVTPropertyNotSupportedErr) {
1385 av_log(avctx,
AV_LOG_WARNING,
"frames_after property is not supported on this device. Ignoring.\n");
1394 CFMutableDictionaryRef par;
1401 num = CFNumberCreate(kCFAllocatorDefault,
1405 den = CFNumberCreate(kCFAllocatorDefault,
1411 par = CFDictionaryCreateMutable(kCFAllocatorDefault,
1413 &kCFCopyStringDictionaryKeyCallBacks,
1414 &kCFTypeDictionaryValueCallBacks);
1416 if (!par || !num || !den) {
1417 if (par) CFRelease(par);
1418 if (num) CFRelease(num);
1419 if (den) CFRelease(den);
1424 CFDictionarySetValue(
1426 kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
1429 CFDictionarySetValue(
1431 kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
1435 kVTCompressionPropertyKey_PixelAspectRatio,
1445 "Error setting pixel aspect ratio to %d:%d: %d.\n",
1457 kVTCompressionPropertyKey_TransferFunction,
1468 kVTCompressionPropertyKey_YCbCrMatrix,
1479 kVTCompressionPropertyKey_ColorPrimaries,
1489 kCVImageBufferGammaLevelKey,
1499 kVTCompressionPropertyKey_AllowFrameReordering,
1514 compat_keys.kVTCompressionPropertyKey_H264EntropyMode,
1525 vtctx->
realtime ? kCFBooleanTrue : kCFBooleanFalse);
1534 compat_keys.kVTCompressionPropertyKey_AllowOpenGOP,
1539 if (avctx->
qmin >= 0) {
1541 compat_keys.kVTCompressionPropertyKey_MinAllowedFrameQP,
1550 if (avctx->
qmax >= 0) {
1552 compat_keys.kVTCompressionPropertyKey_MaxAllowedFrameQP,
1563 kVTCompressionPropertyKey_MaxH264SliceBytes,
1574 compat_keys.kVTCompressionPropertyKey_MaximizePowerEfficiency,
1581 compat_keys.kVTCompressionPropertyKey_ReferenceBufferCount,
1590 status = VTCompressionSessionPrepareToEncodeFrames(vtctx->
session);
1601 CFMutableDictionaryRef enc_info;
1602 CFMutableDictionaryRef pixel_buffer_info =
NULL;
1605 CFStringRef profile_level =
NULL;
1606 CFNumberRef gamma_level =
NULL;
1615 #if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
1617 if (__builtin_available(macOS 10.10, *)) {
1618 VTRegisterProfessionalVideoWorkflowVideoEncoders();
1630 av_log(avctx,
AV_LOG_WARNING,
"Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1635 av_log(avctx,
AV_LOG_WARNING,
"CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1650 enc_info = CFDictionaryCreateMutable(
1651 kCFAllocatorDefault,
1653 &kCFCopyStringDictionaryKeyCallBacks,
1654 &kCFTypeDictionaryValueCallBacks
1657 if (!enc_info)
return AVERROR(ENOMEM);
1659 #if !TARGET_OS_IPHONE
1661 CFDictionarySetValue(enc_info,
1662 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1665 CFDictionarySetValue(enc_info,
1666 compat_keys.kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
1669 CFDictionarySetValue(enc_info,
1670 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1677 CFDictionarySetValue(enc_info,
1678 compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl,
1718 CFRelease(gamma_level);
1720 if (pixel_buffer_info)
1721 CFRelease(pixel_buffer_info);
1723 CFRelease(enc_info);
1731 CFBooleanRef has_b_frames_cfbool;
1746 kVTCompressionPropertyKey_AllowFrameReordering,
1747 kCFAllocatorDefault,
1748 &has_b_frames_cfbool);
1750 if (!
status && has_b_frames_cfbool) {
1753 if (CFBooleanGetValue(has_b_frames_cfbool))
1757 CFRelease(has_b_frames_cfbool);
1766 CFArrayRef attachments;
1767 CFDictionaryRef attachment;
1768 CFBooleanRef not_sync;
1771 attachments = CMSampleBufferGetSampleAttachmentsArray(
buffer,
false);
1772 len = !attachments ? 0 : CFArrayGetCount(attachments);
1775 *is_key_frame =
true;
1779 attachment = CFArrayGetValueAtIndex(attachments, 0);
1781 if (CFDictionaryGetValueIfPresent(attachment,
1782 kCMSampleAttachmentKey_NotSync,
1783 (
const void **)¬_sync))
1785 *is_key_frame = !CFBooleanGetValue(not_sync);
1787 *is_key_frame =
true;
1808 size_t sei_payload_size = 0;
1809 uint8_t *nal_start = nal_data;
1815 nal_type = *nal_data & 0x1F;
1822 if (nal_data[nal_size - 1] == 0x80)
1825 while (nal_size > 0 && *nal_data > 0) {
1829 }
while (nal_size > 0 && *nal_data == 0xFF);
1837 sei_payload_size += *nal_data;
1840 }
while (nal_size > 0 && *nal_data == 0xFF);
1842 if (nal_size < sei_payload_size) {
1847 nal_data += sei_payload_size;
1848 nal_size -= sei_payload_size;
1851 *sei_end = nal_data;
1853 return nal_data - nal_start + 1;
1873 uint8_t* dst_end = dst + dst_size;
1874 const uint8_t* src_end =
src + src_size;
1875 int start_at = dst_offset > 2 ? dst_offset - 2 : 0;
1877 for (
i = start_at;
i < dst_offset &&
i < dst_size;
i++) {
1886 for (;
src < src_end;
src++, dst++) {
1888 int insert_ep3_byte = *
src <= 3;
1889 if (insert_ep3_byte) {
1907 wrote_bytes = dst - dst_start;
1910 return -wrote_bytes;
1920 uint8_t *sei_start = dst;
1921 size_t remaining_sei_size =
sei->size;
1922 size_t remaining_dst_size = dst_size;
1927 if (!remaining_dst_size)
1930 while (sei_type && remaining_dst_size != 0) {
1931 int sei_byte = sei_type > 255 ? 255 : sei_type;
1934 sei_type -= sei_byte;
1936 remaining_dst_size--;
1942 while (remaining_sei_size && remaining_dst_size != 0) {
1943 int size_byte = remaining_sei_size > 255 ? 255 : remaining_sei_size;
1946 remaining_sei_size -= size_byte;
1948 remaining_dst_size--;
1951 if (remaining_dst_size < sei->
size)
1954 header_bytes = dst - sei_start;
1962 if (bytes_written < 0)
1965 bytes_written += header_bytes;
1966 return bytes_written;
1990 size_t length_code_size,
1991 CMSampleBufferRef sample_buffer,
1996 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1997 size_t remaining_src_size = src_size;
1998 size_t remaining_dst_size = dst_size;
1999 size_t src_offset = 0;
2002 uint8_t size_buf[4];
2004 CMBlockBufferRef
block = CMSampleBufferGetDataBuffer(sample_buffer);
2006 if (length_code_size > 4) {
2010 while (remaining_src_size > 0) {
2011 size_t curr_src_len;
2012 size_t curr_dst_len;
2028 src_offset + length_code_size,
2039 for (
i = 0;
i < length_code_size;
i++) {
2041 box_len |= size_buf[
i];
2054 remaining_dst_size--;
2059 remaining_dst_size);
2061 if (wrote_bytes < 0)
2064 remaining_dst_size -= wrote_bytes;
2065 dst_data += wrote_bytes;
2067 if (remaining_dst_size <= 0)
2073 remaining_dst_size--;
2078 curr_src_len = box_len + length_code_size;
2081 if (remaining_src_size < curr_src_len) {
2085 if (remaining_dst_size < curr_dst_len) {
2093 src_offset + length_code_size,
2108 old_sei_length =
find_sei_end(avctx, dst_box, box_len, &new_sei);
2109 if (old_sei_length < 0)
2115 remaining_dst_size - old_sei_length);
2116 if (wrote_bytes < 0)
2119 if (new_sei + wrote_bytes >= dst_data + remaining_dst_size)
2122 new_sei[wrote_bytes++] = 0x80;
2123 extra_bytes = wrote_bytes - (dst_box + box_len - new_sei);
2125 dst_data += extra_bytes;
2126 remaining_dst_size -= extra_bytes;
2131 src_offset += curr_src_len;
2132 dst_data += curr_dst_len;
2134 remaining_src_size -= curr_src_len;
2135 remaining_dst_size -= curr_dst_len;
2156 if ((
sei->size % 255) == 0)
2159 return copied_size +
sei->size / 255 + 1 +
type / 255 + 1;
2164 CMSampleBufferRef sample_buffer,
2173 size_t length_code_size;
2174 size_t header_size = 0;
2176 size_t out_buf_size;
2177 size_t sei_nalu_size = 0;
2179 int64_t time_base_num;
2183 CMVideoFormatDescriptionRef vid_fmt;
2194 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
2212 sei_nalu_size =
sizeof(
start_code) + 1 + msg_size + 1;
2215 in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2216 out_buf_size = header_size +
2245 CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer);
2251 len = CMBlockBufferGetDataLength(buf);
2268 pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
2269 dts = CMSampleBufferGetDecodeTimeStamp (sample_buffer);
2271 if (CMTIME_IS_INVALID(dts)) {
2283 pkt->
dts = dts.value / time_base_num - dts_delta;
2300 size_t *contiguous_buf_size)
2317 if (range_guessed) {
2322 "Color range not set for %s. Using MPEG range.\n",
2329 for (
i = 0;
i <
desc->nb_components;
i++) {
2330 int p =
desc->comp[
i].plane;
2332 bool isAlpha = hasAlpha && (p + 1 == *plane_count);
2333 bool isChroma = (p != 0) && !isAlpha;
2334 int shiftw = isChroma ?
desc->log2_chroma_w : 0;
2335 int shifth = isChroma ?
desc->log2_chroma_h : 0;
2336 widths[p] = (avctx->
width + ((1 << shiftw) >> 1)) >> shiftw;
2337 heights[p] = (avctx->
height + ((1 << shifth) >> 1)) >> shifth;
2341 *contiguous_buf_size = 0;
2342 for (
i = 0;
i < *plane_count;
i++) {
2343 if (
i < *plane_count - 1 &&
2345 *contiguous_buf_size = 0;
2349 *contiguous_buf_size += strides[
i] * heights[
i];
2358 CVPixelBufferRef cv_img,
2359 const size_t *plane_strides,
2360 const size_t *plane_rows)
2372 status = CVPixelBufferLockBaseAddress(cv_img, 0);
2377 "Error: Could not lock base address of CVPixelBuffer: %d.\n",
2382 if (CVPixelBufferIsPlanar(cv_img)) {
2383 plane_count = CVPixelBufferGetPlaneCount(cv_img);
2385 if (
i == plane_count) {
2386 CVPixelBufferUnlockBaseAddress(cv_img, 0);
2389 "Error: different number of planes in AVFrame and CVPixelBuffer.\n"
2395 dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img,
i);
2397 dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img,
i);
2398 src_stride = plane_strides[
i];
2399 rows = plane_rows[
i];
2401 if (dst_stride == src_stride) {
2402 memcpy(dst_addr, src_addr, src_stride * rows);
2404 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2406 for (j = 0; j < rows; j++) {
2407 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2413 CVPixelBufferUnlockBaseAddress(cv_img, 0);
2416 "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
2422 dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
2424 dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
2425 src_stride = plane_strides[0];
2426 rows = plane_rows[0];
2428 if (dst_stride == src_stride) {
2429 memcpy(dst_addr, src_addr, src_stride * rows);
2431 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2433 for (j = 0; j < rows; j++) {
2434 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2439 status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
2450 CVPixelBufferRef *cv_img)
2458 size_t contiguous_buf_size;
2459 CVPixelBufferPoolRef pix_buf_pool;
2465 *cv_img = (CVPixelBufferRef)
frame->
data[3];
2472 memset(widths, 0,
sizeof(widths));
2473 memset(heights, 0,
sizeof(heights));
2474 memset(strides, 0,
sizeof(strides));
2484 &contiguous_buf_size
2491 "Error: Cannot convert format %d color_range %d: %d\n",
2500 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2501 if (!pix_buf_pool) {
2508 vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->
session);
2509 if (vtstatus == kVTInvalidSessionErr) {
2514 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2516 if (!pix_buf_pool) {
2522 "kVTInvalidSessionErr error.\n");
2525 status = CVPixelBufferPoolCreatePixelBuffer(
NULL,
2546 CFDictionaryRef* dict_out)
2548 CFDictionaryRef dict =
NULL;
2550 const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
2551 const void *vals[] = { kCFBooleanTrue };
2553 dict = CFDictionaryCreate(
NULL, keys, vals, 1,
NULL,
NULL);
2554 if(!dict)
return AVERROR(ENOMEM);
2566 CFDictionaryRef frame_dict;
2567 CVPixelBufferRef cv_img =
NULL;
2582 if (vtctx->
a53_cc && side_data && side_data->
size) {
2598 status = VTCompressionSessionEncodeFrame(
2608 if (frame_dict) CFRelease(frame_dict);
2628 CMSampleBufferRef buf =
NULL;
2667 if (
status)
goto end_nopkt;
2668 if (!buf)
goto end_nopkt;
2676 if (
status)
goto end_nopkt;
2688 CFStringRef profile_level,
2689 CFNumberRef gamma_level,
2690 CFDictionaryRef enc_info,
2691 CFDictionaryRef pixel_buffer_info)
2695 CVPixelBufferPoolRef pool =
NULL;
2696 CVPixelBufferRef pix_buf =
NULL;
2698 CMSampleBufferRef buf =
NULL;
2711 pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2718 status = CVPixelBufferPoolCreatePixelBuffer(
NULL,
2722 if(
status != kCVReturnSuccess){
2740 "Error sending frame for extradata: %d\n",
2766 CVPixelBufferRelease(pix_buf);
2785 VTCompressionSessionCompleteFrames(vtctx->
session,
2815 #ifdef kCFCoreFoundationVersionNumber10_7
2820 #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
2823 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
2826 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
2829 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
2832 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
2835 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
2838 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
2845 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
2846 #define COMMON_OPTIONS \
2847 { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \
2848 { .i64 = 0 }, 0, 1, VE }, \
2849 { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
2850 { .i64 = 0 }, 0, 1, VE }, \
2851 { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
2852 OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \
2853 { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
2854 OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2855 { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \
2856 OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2857 { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \
2858 { .i64 = -1 }, -1, 1, VE }, \
2859 { "power_efficient", "Set to 1 to enable more power-efficient encoding if supported.", \
2860 OFFSET(power_efficient), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2861 { "max_ref_frames", \
2862 "Sets the maximum number of reference frames. This only has an effect when the value is less than the maximum allowed by the profile/level.", \
2863 OFFSET(max_ref_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
2870 #define OFFSET(x) offsetof(VTEncContext, x)
2881 {
"1.3",
"Level 1.3, only available with Baseline Profile", 0,
AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX,
VE,
"level" },
2882 {
"3.0",
"Level 3.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX,
VE,
"level" },
2883 {
"3.1",
"Level 3.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX,
VE,
"level" },
2884 {
"3.2",
"Level 3.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX,
VE,
"level" },
2885 {
"4.0",
"Level 4.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX,
VE,
"level" },
2886 {
"4.1",
"Level 4.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX,
VE,
"level" },
2887 {
"4.2",
"Level 4.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX,
VE,
"level" },
2888 {
"5.0",
"Level 5.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX,
VE,
"level" },
2889 {
"5.1",
"Level 5.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX,
VE,
"level" },
2890 {
"5.2",
"Level 5.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX,
VE,
"level" },
2900 {
"constant_bit_rate",
"Require constant bit rate (macOS 13 or newer)",
OFFSET(constant_bit_rate),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VE },
2901 {
"max_slice_bytes",
"Set the maximum number of bytes in an H.264 slice.",
OFFSET(max_slice_bytes),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX,
VE },
2914 .
p.
name =
"h264_videotoolbox",
2934 {
"alpha_quality",
"Compression quality for the alpha channel",
OFFSET(alpha_quality),
AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0,
VE },
2936 {
"constant_bit_rate",
"Require constant bit rate (macOS 13 or newer)",
OFFSET(constant_bit_rate),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VE },
2950 .
p.
name =
"hevc_videotoolbox",
2963 .p.wrapper_name =
"videotoolbox",
2989 .
p.
name =
"prores_videotoolbox",
3002 .p.wrapper_name =
"videotoolbox",