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)
528 return MKBETAG(
'a',
'p',
'c',
'o');
530 return MKBETAG(
'a',
'p',
'c',
's');
532 return MKBETAG(
'a',
'p',
'c',
'n');
534 return MKBETAG(
'a',
'p',
'c',
'h');
536 return MKBETAG(
'a',
'p',
'4',
'h');
538 return MKBETAG(
'a',
'p',
'4',
'x');
545 desc->log2_chroma_w == 0))
546 return MKBETAG(
'a',
'p',
'4',
'h');
548 return MKBETAG(
'a',
'p',
'c',
'n');
564 CMVideoFormatDescriptionRef vid_fmt,
568 size_t total_size = 0;
570 int is_count_bad = 0;
585 for (
i = 0;
i < ps_count || is_count_bad;
i++) {
599 if (
i > 0 && is_count_bad)
status = 0;
618 CMVideoFormatDescriptionRef vid_fmt,
624 int is_count_bad = 0;
642 for (
i = 0;
i < ps_count || is_count_bad;
i++) {
654 if (
i > 0 && is_count_bad)
status = 0;
660 if (dst_size < next_offset) {
668 memcpy(dst +
offset, ps, ps_size);
683 CMVideoFormatDescriptionRef vid_fmt;
687 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
713 CFDataRef
data = CMFormatDescriptionGetExtension(vid_fmt, kCMFormatDescriptionExtension_VerbatimSampleDescription);
714 if (
data && CFGetTypeID(
data) == CFDataGetTypeID()) {
715 CFIndex
size = CFDataGetLength(
data);
731 void *sourceFrameCtx,
733 VTEncodeInfoFlags
flags,
734 CMSampleBufferRef sample_buffer)
750 if (!sample_buffer) {
767 CMSampleBufferRef sample_buffer,
771 CMVideoFormatDescriptionRef vid_fmt;
775 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
803 CFStringRef *profile_level_val)
813 *profile_level_val =
NULL;
820 switch (vtctx->
level) {
821 case 0: *profile_level_val =
822 compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel;
break;
823 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3;
break;
824 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0;
break;
825 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1;
break;
826 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2;
break;
827 case 40: *profile_level_val =
828 compat_keys.kVTProfileLevel_H264_Baseline_4_0;
break;
829 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1;
break;
830 case 42: *profile_level_val =
831 compat_keys.kVTProfileLevel_H264_Baseline_4_2;
break;
832 case 50: *profile_level_val =
833 compat_keys.kVTProfileLevel_H264_Baseline_5_0;
break;
834 case 51: *profile_level_val =
835 compat_keys.kVTProfileLevel_H264_Baseline_5_1;
break;
836 case 52: *profile_level_val =
837 compat_keys.kVTProfileLevel_H264_Baseline_5_2;
break;
842 *profile_level_val =
compat_keys.kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel;
844 if (vtctx->
level != 0) {
847 "Level is auto-selected when constrained-baseline "
848 "profile is used. The output may be encoded with a "
849 "different level.\n");
854 switch (vtctx->
level) {
855 case 0: *profile_level_val =
856 compat_keys.kVTProfileLevel_H264_Main_AutoLevel;
break;
857 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0;
break;
858 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1;
break;
859 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2;
break;
860 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0;
break;
861 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1;
break;
862 case 42: *profile_level_val =
864 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0;
break;
865 case 51: *profile_level_val =
867 case 52: *profile_level_val =
873 *profile_level_val =
compat_keys.kVTProfileLevel_H264_ConstrainedHigh_AutoLevel;
875 if (vtctx->
level != 0) {
878 "Level is auto-selected when constrained-high profile "
879 "is used. The output may be encoded with a different "
885 switch (vtctx->
level) {
886 case 0: *profile_level_val =
887 compat_keys.kVTProfileLevel_H264_High_AutoLevel;
break;
888 case 30: *profile_level_val =
890 case 31: *profile_level_val =
892 case 32: *profile_level_val =
894 case 40: *profile_level_val =
896 case 41: *profile_level_val =
898 case 42: *profile_level_val =
900 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0;
break;
901 case 51: *profile_level_val =
903 case 52: *profile_level_val =
908 switch (vtctx->
level) {
909 case 0: *profile_level_val =
910 compat_keys.kVTProfileLevel_H264_Extended_AutoLevel;
break;
911 case 50: *profile_level_val =
912 compat_keys.kVTProfileLevel_H264_Extended_5_0;
break;
917 if (!*profile_level_val) {
932 CFStringRef *profile_level_val)
941 *profile_level_val =
NULL;
955 "main profile with %d bit input\n",
bit_depth);
962 "Invalid main10 profile with %d bit input\n",
bit_depth);
970 if (!*profile_level_val) {
981 int* av_pixel_format,
984 const char *range_name;
990 if (*av_pixel_format)
995 "Could not get pixel format for color format '%s' range '%s'.\n",
997 range_name ? range_name :
"Unknown");
1006 CFDictionarySetValue(dict,
1007 kCVImageBufferColorPrimariesKey,
1012 CFDictionarySetValue(dict,
1013 kCVImageBufferTransferFunctionKey,
1018 CFDictionarySetValue(dict,
1019 kCVImageBufferYCbCrMatrixKey,
1025 CFMutableDictionaryRef* dict)
1027 CFNumberRef cv_color_format_num =
NULL;
1028 CFNumberRef width_num =
NULL;
1029 CFNumberRef height_num =
NULL;
1030 CFMutableDictionaryRef pixel_buffer_info =
NULL;
1031 int cv_color_format;
1039 pixel_buffer_info = CFDictionaryCreateMutable(
1040 kCFAllocatorDefault,
1042 &kCFCopyStringDictionaryKeyCallBacks,
1043 &kCFTypeDictionaryValueCallBacks);
1045 if (!pixel_buffer_info)
goto pbinfo_nomem;
1047 cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
1048 kCFNumberSInt32Type,
1050 if (!cv_color_format_num)
goto pbinfo_nomem;
1052 CFDictionarySetValue(pixel_buffer_info,
1053 kCVPixelBufferPixelFormatTypeKey,
1054 cv_color_format_num);
1057 width_num = CFNumberCreate(kCFAllocatorDefault,
1058 kCFNumberSInt32Type,
1060 if (!width_num)
goto pbinfo_nomem;
1062 CFDictionarySetValue(pixel_buffer_info,
1063 kCVPixelBufferWidthKey,
1067 height_num = CFNumberCreate(kCFAllocatorDefault,
1068 kCFNumberSInt32Type,
1070 if (!height_num)
goto pbinfo_nomem;
1072 CFDictionarySetValue(pixel_buffer_info,
1073 kCVPixelBufferHeightKey,
1079 *dict = pixel_buffer_info;
1086 if (pixel_buffer_info) CFRelease(pixel_buffer_info);
1092 CFNumberRef *gamma_level)
1096 *gamma_level =
NULL;
1104 *gamma_level = CFNumberCreate(
NULL, kCFNumberFloat32Type, &gamma);
1116 const char *print_option_name,
1122 if (
status == kVTPropertyNotSupportedErr) {
1125 "This device does not support the %s option. Value ignored.\n",
1127 }
else if (
status != 0) {
1130 "Error setting %s: Error %d\n",
1138 const char* print_option_name,
1140 CFNumberRef value_cfnum = CFNumberCreate(kCFAllocatorDefault,
1144 if (value_cfnum ==
NULL) {
1150 CFRelease(value_cfnum);
1157 CFStringRef profile_level,
1158 CFNumberRef gamma_level,
1159 CFDictionaryRef enc_info,
1160 CFDictionaryRef pixel_buffer_info,
1161 bool constant_bit_rate,
1162 VTCompressionSessionRef *session)
1168 CFNumberRef bit_rate_num;
1169 CFNumberRef quality_num;
1170 CFNumberRef bytes_per_second;
1171 CFNumberRef one_second;
1172 CFArrayRef data_rate_limits;
1173 int64_t bytes_per_second_value = 0;
1177 int status = VTCompressionSessionCreate(kCFAllocatorDefault,
1183 kCFAllocatorDefault,
1191 #if !TARGET_OS_IPHONE
1193 av_log(avctx,
AV_LOG_ERROR,
"Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
1200 #if defined (MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13)
1201 if (__builtin_available(macOS 10.13, *)) {
1202 status = VTCopySupportedPropertyDictionaryForEncoder(avctx->
width,
1221 av_log(avctx,
AV_LOG_ERROR,
"Error: -q:v qscale not available for encoder. Use -b:v bitrate instead.\n");
1227 quality_num = CFNumberCreate(kCFAllocatorDefault,
1228 kCFNumberFloat32Type,
1230 if (!quality_num)
return AVERROR(ENOMEM);
1233 kVTCompressionPropertyKey_Quality,
1235 CFRelease(quality_num);
1237 bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
1238 kCFNumberSInt32Type,
1240 if (!bit_rate_num)
return AVERROR(ENOMEM);
1242 if (constant_bit_rate) {
1244 compat_keys.kVTCompressionPropertyKey_ConstantBitRate,
1246 if (
status == kVTPropertyNotSupportedErr) {
1247 av_log(avctx,
AV_LOG_ERROR,
"Error: -constant_bit_rate true is not supported by the encoder.\n");
1252 kVTCompressionPropertyKey_AverageBitRate,
1256 CFRelease(bit_rate_num);
1266 compat_keys.kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality,
1267 vtctx->
prio_speed ? kCFBooleanTrue : kCFBooleanFalse);
1269 av_log(avctx,
AV_LOG_WARNING,
"PrioritizeEncodingSpeedOverQuality property is not supported on this device. Ignoring.\n");
1275 bytes_per_second_value = max_rate >> 3;
1276 bytes_per_second = CFNumberCreate(kCFAllocatorDefault,
1277 kCFNumberSInt64Type,
1278 &bytes_per_second_value);
1279 if (!bytes_per_second) {
1282 one_second_value = 1;
1283 one_second = CFNumberCreate(kCFAllocatorDefault,
1284 kCFNumberSInt64Type,
1287 CFRelease(bytes_per_second);
1290 nums[0] = (
void *)bytes_per_second;
1291 nums[1] = (
void *)one_second;
1292 data_rate_limits = CFArrayCreate(kCFAllocatorDefault,
1293 (
const void **)nums,
1295 &kCFTypeArrayCallBacks);
1297 if (!data_rate_limits) {
1298 CFRelease(bytes_per_second);
1299 CFRelease(one_second);
1303 kVTCompressionPropertyKey_DataRateLimits,
1306 CFRelease(bytes_per_second);
1307 CFRelease(one_second);
1308 CFRelease(data_rate_limits);
1322 CFNumberRef alpha_quality_num = CFNumberCreate(kCFAllocatorDefault,
1323 kCFNumberDoubleType,
1325 if (!alpha_quality_num)
return AVERROR(ENOMEM);
1328 compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha,
1330 CFRelease(alpha_quality_num);
1335 "Error setting alpha quality: %d\n",
1341 if (profile_level) {
1343 kVTCompressionPropertyKey_ProfileLevel,
1346 av_log(avctx,
AV_LOG_ERROR,
"Error setting profile/level property: %d. Output will be encoded using a supported profile/level combination.\n",
status);
1351 CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
1359 kVTCompressionPropertyKey_MaxKeyFrameInterval,
1361 CFRelease(interval);
1371 kVTCompressionPropertyKey_MoreFramesBeforeStart,
1374 if (
status == kVTPropertyNotSupportedErr) {
1375 av_log(avctx,
AV_LOG_WARNING,
"frames_before property is not supported on this device. Ignoring.\n");
1383 kVTCompressionPropertyKey_MoreFramesAfterEnd,
1386 if (
status == kVTPropertyNotSupportedErr) {
1387 av_log(avctx,
AV_LOG_WARNING,
"frames_after property is not supported on this device. Ignoring.\n");
1396 CFMutableDictionaryRef par;
1403 num = CFNumberCreate(kCFAllocatorDefault,
1407 den = CFNumberCreate(kCFAllocatorDefault,
1413 par = CFDictionaryCreateMutable(kCFAllocatorDefault,
1415 &kCFCopyStringDictionaryKeyCallBacks,
1416 &kCFTypeDictionaryValueCallBacks);
1418 if (!par || !num || !den) {
1419 if (par) CFRelease(par);
1420 if (num) CFRelease(num);
1421 if (den) CFRelease(den);
1426 CFDictionarySetValue(
1428 kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
1431 CFDictionarySetValue(
1433 kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
1437 kVTCompressionPropertyKey_PixelAspectRatio,
1447 "Error setting pixel aspect ratio to %d:%d: %d.\n",
1459 kVTCompressionPropertyKey_TransferFunction,
1470 kVTCompressionPropertyKey_YCbCrMatrix,
1481 kVTCompressionPropertyKey_ColorPrimaries,
1491 kCVImageBufferGammaLevelKey,
1501 kVTCompressionPropertyKey_AllowFrameReordering,
1516 compat_keys.kVTCompressionPropertyKey_H264EntropyMode,
1527 vtctx->
realtime ? kCFBooleanTrue : kCFBooleanFalse);
1536 compat_keys.kVTCompressionPropertyKey_AllowOpenGOP,
1541 if (avctx->
qmin >= 0) {
1543 compat_keys.kVTCompressionPropertyKey_MinAllowedFrameQP,
1552 if (avctx->
qmax >= 0) {
1554 compat_keys.kVTCompressionPropertyKey_MaxAllowedFrameQP,
1565 kVTCompressionPropertyKey_MaxH264SliceBytes,
1576 compat_keys.kVTCompressionPropertyKey_MaximizePowerEfficiency,
1583 compat_keys.kVTCompressionPropertyKey_ReferenceBufferCount,
1592 status = VTCompressionSessionPrepareToEncodeFrames(vtctx->
session);
1603 CFMutableDictionaryRef enc_info;
1604 CFMutableDictionaryRef pixel_buffer_info =
NULL;
1607 CFStringRef profile_level =
NULL;
1608 CFNumberRef gamma_level =
NULL;
1617 #if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
1619 if (__builtin_available(macOS 10.10, *)) {
1620 VTRegisterProfessionalVideoWorkflowVideoEncoders();
1632 av_log(avctx,
AV_LOG_WARNING,
"Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1637 av_log(avctx,
AV_LOG_WARNING,
"CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1652 enc_info = CFDictionaryCreateMutable(
1653 kCFAllocatorDefault,
1655 &kCFCopyStringDictionaryKeyCallBacks,
1656 &kCFTypeDictionaryValueCallBacks
1659 if (!enc_info)
return AVERROR(ENOMEM);
1661 #if !TARGET_OS_IPHONE
1663 CFDictionarySetValue(enc_info,
1664 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1667 CFDictionarySetValue(enc_info,
1668 compat_keys.kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
1671 CFDictionarySetValue(enc_info,
1672 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1679 CFDictionarySetValue(enc_info,
1680 compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl,
1720 CFRelease(gamma_level);
1722 if (pixel_buffer_info)
1723 CFRelease(pixel_buffer_info);
1725 CFRelease(enc_info);
1733 CFBooleanRef has_b_frames_cfbool;
1748 kVTCompressionPropertyKey_AllowFrameReordering,
1749 kCFAllocatorDefault,
1750 &has_b_frames_cfbool);
1752 if (!
status && has_b_frames_cfbool) {
1755 if (CFBooleanGetValue(has_b_frames_cfbool))
1759 CFRelease(has_b_frames_cfbool);
1768 CFArrayRef attachments;
1769 CFDictionaryRef attachment;
1770 CFBooleanRef not_sync;
1773 attachments = CMSampleBufferGetSampleAttachmentsArray(
buffer,
false);
1774 len = !attachments ? 0 : CFArrayGetCount(attachments);
1777 *is_key_frame =
true;
1781 attachment = CFArrayGetValueAtIndex(attachments, 0);
1783 if (CFDictionaryGetValueIfPresent(attachment,
1784 kCMSampleAttachmentKey_NotSync,
1785 (
const void **)¬_sync))
1787 *is_key_frame = !CFBooleanGetValue(not_sync);
1789 *is_key_frame =
true;
1810 size_t sei_payload_size = 0;
1811 uint8_t *nal_start = nal_data;
1817 nal_type = *nal_data & 0x1F;
1824 if (nal_data[nal_size - 1] == 0x80)
1827 while (nal_size > 0 && *nal_data > 0) {
1831 }
while (nal_size > 0 && *nal_data == 0xFF);
1839 sei_payload_size += *nal_data;
1842 }
while (nal_size > 0 && *nal_data == 0xFF);
1844 if (nal_size < sei_payload_size) {
1849 nal_data += sei_payload_size;
1850 nal_size -= sei_payload_size;
1853 *sei_end = nal_data;
1855 return nal_data - nal_start + 1;
1875 uint8_t* dst_end = dst + dst_size;
1876 const uint8_t* src_end =
src + src_size;
1877 int start_at = dst_offset > 2 ? dst_offset - 2 : 0;
1879 for (
i = start_at;
i < dst_offset &&
i < dst_size;
i++) {
1888 for (;
src < src_end;
src++, dst++) {
1890 int insert_ep3_byte = *
src <= 3;
1891 if (insert_ep3_byte) {
1909 wrote_bytes = dst - dst_start;
1912 return -wrote_bytes;
1922 uint8_t *sei_start = dst;
1923 size_t remaining_sei_size =
sei->size;
1924 size_t remaining_dst_size = dst_size;
1929 if (!remaining_dst_size)
1932 while (sei_type && remaining_dst_size != 0) {
1933 int sei_byte = sei_type > 255 ? 255 : sei_type;
1936 sei_type -= sei_byte;
1938 remaining_dst_size--;
1944 while (remaining_sei_size && remaining_dst_size != 0) {
1945 int size_byte = remaining_sei_size > 255 ? 255 : remaining_sei_size;
1948 remaining_sei_size -= size_byte;
1950 remaining_dst_size--;
1953 if (remaining_dst_size < sei->
size)
1956 header_bytes = dst - sei_start;
1964 if (bytes_written < 0)
1967 bytes_written += header_bytes;
1968 return bytes_written;
1992 size_t length_code_size,
1993 CMSampleBufferRef sample_buffer,
1998 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1999 size_t remaining_src_size = src_size;
2000 size_t remaining_dst_size = dst_size;
2001 size_t src_offset = 0;
2004 uint8_t size_buf[4];
2006 CMBlockBufferRef
block = CMSampleBufferGetDataBuffer(sample_buffer);
2008 if (length_code_size > 4) {
2012 while (remaining_src_size > 0) {
2013 size_t curr_src_len;
2014 size_t curr_dst_len;
2030 src_offset + length_code_size,
2041 for (
i = 0;
i < length_code_size;
i++) {
2043 box_len |= size_buf[
i];
2056 remaining_dst_size--;
2061 remaining_dst_size);
2063 if (wrote_bytes < 0)
2066 remaining_dst_size -= wrote_bytes;
2067 dst_data += wrote_bytes;
2069 if (remaining_dst_size <= 0)
2075 remaining_dst_size--;
2080 curr_src_len = box_len + length_code_size;
2083 if (remaining_src_size < curr_src_len) {
2087 if (remaining_dst_size < curr_dst_len) {
2095 src_offset + length_code_size,
2110 old_sei_length =
find_sei_end(avctx, dst_box, box_len, &new_sei);
2111 if (old_sei_length < 0)
2117 remaining_dst_size - old_sei_length);
2118 if (wrote_bytes < 0)
2121 if (new_sei + wrote_bytes >= dst_data + remaining_dst_size)
2124 new_sei[wrote_bytes++] = 0x80;
2125 extra_bytes = wrote_bytes - (dst_box + box_len - new_sei);
2127 dst_data += extra_bytes;
2128 remaining_dst_size -= extra_bytes;
2133 src_offset += curr_src_len;
2134 dst_data += curr_dst_len;
2136 remaining_src_size -= curr_src_len;
2137 remaining_dst_size -= curr_dst_len;
2158 if ((
sei->size % 255) == 0)
2161 return copied_size +
sei->size / 255 + 1 +
type / 255 + 1;
2166 CMSampleBufferRef sample_buffer,
2175 size_t length_code_size;
2176 size_t header_size = 0;
2178 size_t out_buf_size;
2179 size_t sei_nalu_size = 0;
2185 CMVideoFormatDescriptionRef vid_fmt;
2196 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
2214 sei_nalu_size =
sizeof(
start_code) + 1 + msg_size + 1;
2217 in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2218 out_buf_size = header_size +
2247 CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer);
2253 len = CMBlockBufferGetDataLength(buf);
2270 pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
2271 dts = CMSampleBufferGetDecodeTimeStamp (sample_buffer);
2273 if (CMTIME_IS_INVALID(dts)) {
2285 pkt->
dts = dts.value / time_base_num - dts_delta;
2302 size_t *contiguous_buf_size)
2319 if (range_guessed) {
2324 "Color range not set for %s. Using MPEG range.\n",
2331 for (
i = 0;
i <
desc->nb_components;
i++) {
2332 int p =
desc->comp[
i].plane;
2334 bool isAlpha = hasAlpha && (p + 1 == *plane_count);
2335 bool isChroma = (p != 0) && !isAlpha;
2336 int shiftw = isChroma ?
desc->log2_chroma_w : 0;
2337 int shifth = isChroma ?
desc->log2_chroma_h : 0;
2338 widths[p] = (avctx->
width + ((1 << shiftw) >> 1)) >> shiftw;
2339 heights[p] = (avctx->
height + ((1 << shifth) >> 1)) >> shifth;
2343 *contiguous_buf_size = 0;
2344 for (
i = 0;
i < *plane_count;
i++) {
2345 if (
i < *plane_count - 1 &&
2347 *contiguous_buf_size = 0;
2351 *contiguous_buf_size += strides[
i] * heights[
i];
2360 CVPixelBufferRef cv_img,
2361 const size_t *plane_strides,
2362 const size_t *plane_rows)
2374 status = CVPixelBufferLockBaseAddress(cv_img, 0);
2379 "Error: Could not lock base address of CVPixelBuffer: %d.\n",
2384 if (CVPixelBufferIsPlanar(cv_img)) {
2385 plane_count = CVPixelBufferGetPlaneCount(cv_img);
2387 if (
i == plane_count) {
2388 CVPixelBufferUnlockBaseAddress(cv_img, 0);
2391 "Error: different number of planes in AVFrame and CVPixelBuffer.\n"
2397 dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img,
i);
2399 dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img,
i);
2400 src_stride = plane_strides[
i];
2401 rows = plane_rows[
i];
2403 if (dst_stride == src_stride) {
2404 memcpy(dst_addr, src_addr, src_stride * rows);
2406 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2408 for (j = 0; j < rows; j++) {
2409 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2415 CVPixelBufferUnlockBaseAddress(cv_img, 0);
2418 "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
2424 dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
2426 dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
2427 src_stride = plane_strides[0];
2428 rows = plane_rows[0];
2430 if (dst_stride == src_stride) {
2431 memcpy(dst_addr, src_addr, src_stride * rows);
2433 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2435 for (j = 0; j < rows; j++) {
2436 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2441 status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
2452 CVPixelBufferRef *cv_img)
2460 size_t contiguous_buf_size;
2461 CVPixelBufferPoolRef pix_buf_pool;
2467 *cv_img = (CVPixelBufferRef)
frame->
data[3];
2474 memset(widths, 0,
sizeof(widths));
2475 memset(heights, 0,
sizeof(heights));
2476 memset(strides, 0,
sizeof(strides));
2486 &contiguous_buf_size
2493 "Error: Cannot convert format %d color_range %d: %d\n",
2502 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2503 if (!pix_buf_pool) {
2510 vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->
session);
2511 if (vtstatus == kVTInvalidSessionErr) {
2516 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2518 if (!pix_buf_pool) {
2524 "kVTInvalidSessionErr error.\n");
2527 status = CVPixelBufferPoolCreatePixelBuffer(
NULL,
2548 CFDictionaryRef* dict_out)
2550 CFDictionaryRef dict =
NULL;
2552 const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
2553 const void *vals[] = { kCFBooleanTrue };
2555 dict = CFDictionaryCreate(
NULL, keys, vals, 1,
NULL,
NULL);
2556 if(!dict)
return AVERROR(ENOMEM);
2568 CFDictionaryRef frame_dict;
2569 CVPixelBufferRef cv_img =
NULL;
2584 if (vtctx->
a53_cc && side_data && side_data->
size) {
2600 status = VTCompressionSessionEncodeFrame(
2610 if (frame_dict) CFRelease(frame_dict);
2630 CMSampleBufferRef buf =
NULL;
2669 if (
status)
goto end_nopkt;
2670 if (!buf)
goto end_nopkt;
2678 if (
status)
goto end_nopkt;
2690 CFStringRef profile_level,
2691 CFNumberRef gamma_level,
2692 CFDictionaryRef enc_info,
2693 CFDictionaryRef pixel_buffer_info)
2697 CVPixelBufferPoolRef pool =
NULL;
2698 CVPixelBufferRef pix_buf =
NULL;
2700 CMSampleBufferRef buf =
NULL;
2713 pool = VTCompressionSessionGetPixelBufferPool(vtctx->
session);
2720 status = CVPixelBufferPoolCreatePixelBuffer(
NULL,
2724 if(
status != kCVReturnSuccess){
2742 "Error sending frame for extradata: %d\n",
2768 CVPixelBufferRelease(pix_buf);
2787 VTCompressionSessionCompleteFrames(vtctx->
session,
2817 #ifdef kCFCoreFoundationVersionNumber10_7
2822 #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
2825 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
2828 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
2831 #if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
2834 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
2837 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
2840 #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
2847 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
2848 #define COMMON_OPTIONS \
2849 { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \
2850 { .i64 = 0 }, 0, 1, VE }, \
2851 { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
2852 { .i64 = 0 }, 0, 1, VE }, \
2853 { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
2854 OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \
2855 { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
2856 OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2857 { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \
2858 OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2859 { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \
2860 { .i64 = -1 }, -1, 1, VE }, \
2861 { "power_efficient", "Set to 1 to enable more power-efficient encoding if supported.", \
2862 OFFSET(power_efficient), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2863 { "max_ref_frames", \
2864 "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.", \
2865 OFFSET(max_ref_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
2872 #define OFFSET(x) offsetof(VTEncContext, x)
2883 {
"1.3",
"Level 1.3, only available with Baseline Profile", 0,
AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2884 {
"3.0",
"Level 3.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2885 {
"3.1",
"Level 3.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2886 {
"3.2",
"Level 3.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2887 {
"4.0",
"Level 4.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2888 {
"4.1",
"Level 4.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2889 {
"4.2",
"Level 4.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2890 {
"5.0",
"Level 5.0", 0,
AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2891 {
"5.1",
"Level 5.1", 0,
AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2892 {
"5.2",
"Level 5.2", 0,
AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX,
VE, .unit =
"level" },
2902 {
"constant_bit_rate",
"Require constant bit rate (macOS 13 or newer)",
OFFSET(constant_bit_rate),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VE },
2903 {
"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 },
2922 .
p.
name =
"h264_videotoolbox",
2943 {
"alpha_quality",
"Compression quality for the alpha channel",
OFFSET(alpha_quality),
AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0,
VE },
2945 {
"constant_bit_rate",
"Require constant bit rate (macOS 13 or newer)",
OFFSET(constant_bit_rate),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VE },
2959 .
p.
name =
"hevc_videotoolbox",
2973 .p.wrapper_name =
"videotoolbox",
2999 .
p.
name =
"prores_videotoolbox",
3013 .p.wrapper_name =
"videotoolbox",