@ -34,12 +34,91 @@
# include <pthread.h>
# include "h264.h"
# include "h264_sei.h"
# if !CONFIG_VT_BT2020
# define kCVImageBufferColorPrimaries_ITU_R_2020 CFSTR("ITU_R_2020")
# define kCVImageBufferTransferFunction_ITU_R_2020 CFSTR("ITU_R_2020")
# define kCVImageBufferYCbCrMatrix_ITU_R_2020 CFSTR("ITU_R_2020")
# endif
# include <dlfcn.h>
//These symbols may not be present
static struct {
CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020 ;
CFStringRef kCVImageBufferTransferFunction_ITU_R_2020 ;
CFStringRef kCVImageBufferYCbCrMatrix_ITU_R_2020 ;
CFStringRef kVTCompressionPropertyKey_H264EntropyMode ;
CFStringRef kVTH264EntropyMode_CAVLC ;
CFStringRef kVTH264EntropyMode_CABAC ;
CFStringRef kVTProfileLevel_H264_Baseline_4_0 ;
CFStringRef kVTProfileLevel_H264_Baseline_4_2 ;
CFStringRef kVTProfileLevel_H264_Baseline_5_0 ;
CFStringRef kVTProfileLevel_H264_Baseline_5_1 ;
CFStringRef kVTProfileLevel_H264_Baseline_5_2 ;
CFStringRef kVTProfileLevel_H264_Baseline_AutoLevel ;
CFStringRef kVTProfileLevel_H264_Main_4_2 ;
CFStringRef kVTProfileLevel_H264_Main_5_1 ;
CFStringRef kVTProfileLevel_H264_Main_5_2 ;
CFStringRef kVTProfileLevel_H264_Main_AutoLevel ;
CFStringRef kVTProfileLevel_H264_High_3_0 ;
CFStringRef kVTProfileLevel_H264_High_3_1 ;
CFStringRef kVTProfileLevel_H264_High_3_2 ;
CFStringRef kVTProfileLevel_H264_High_4_0 ;
CFStringRef kVTProfileLevel_H264_High_4_1 ;
CFStringRef kVTProfileLevel_H264_High_4_2 ;
CFStringRef kVTProfileLevel_H264_High_5_1 ;
CFStringRef kVTProfileLevel_H264_High_5_2 ;
CFStringRef kVTProfileLevel_H264_High_AutoLevel ;
CFStringRef kVTCompressionPropertyKey_RealTime ;
CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder ;
CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder ;
} compat_keys ;
# define GET_SYM(symbol, defaultVal) \
do { \
CFStringRef cfstr = dlsym ( RTLD_DEFAULT , # symbol ) ; \
if ( ! cfstr ) \
compat_keys . symbol = CFSTR ( defaultVal ) ; \
else \
compat_keys . symbol = symbol ; \
} while ( 0 )
static pthread_once_t once_ctrl = PTHREAD_ONCE_INIT ;
static void loadVTEncSymbols ( ) {
GET_SYM ( kCVImageBufferColorPrimaries_ITU_R_2020 , " ITU_R_2020 " ) ;
GET_SYM ( kCVImageBufferTransferFunction_ITU_R_2020 , " ITU_R_2020 " ) ;
GET_SYM ( kCVImageBufferYCbCrMatrix_ITU_R_2020 , " ITU_R_2020 " ) ;
GET_SYM ( kVTCompressionPropertyKey_H264EntropyMode , " H264EntropyMode " ) ;
GET_SYM ( kVTH264EntropyMode_CAVLC , " CAVLC " ) ;
GET_SYM ( kVTH264EntropyMode_CABAC , " CABAC " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_4_0 , " H264_Baseline_4_0 " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_4_2 , " H264_Baseline_4_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_5_0 , " H264_Baseline_5_0 " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_5_1 , " H264_Baseline_5_1 " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_5_2 , " H264_Baseline_5_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_Baseline_AutoLevel , " H264_Baseline_AutoLevel " ) ;
GET_SYM ( kVTProfileLevel_H264_Main_4_2 , " H264_Main_4_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_Main_5_1 , " H264_Main_5_1 " ) ;
GET_SYM ( kVTProfileLevel_H264_Main_5_2 , " H264_Main_5_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_Main_AutoLevel , " H264_Main_AutoLevel " ) ;
GET_SYM ( kVTProfileLevel_H264_High_3_0 , " H264_High_3_0 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_3_1 , " H264_High_3_1 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_3_2 , " H264_High_3_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_4_0 , " H264_High_4_0 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_4_1 , " H264_High_4_1 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_4_2 , " H264_High_4_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_5_1 , " H264_High_5_1 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_5_2 , " H264_High_5_2 " ) ;
GET_SYM ( kVTProfileLevel_H264_High_AutoLevel , " H264_High_AutoLevel " ) ;
GET_SYM ( kVTCompressionPropertyKey_RealTime , " RealTime " ) ;
GET_SYM ( kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder ,
" EnableHardwareAcceleratedVideoEncoder " ) ;
GET_SYM ( kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder ,
" RequireHardwareAcceleratedVideoEncoder " ) ;
}
typedef enum VT_H264Profile {
H264_PROF_AUTO ,
@ -520,47 +599,66 @@ static bool get_vt_profile_level(AVCodecContext *avctx,
case H264_PROF_BASELINE :
switch ( vtctx - > level ) {
case 0 : * profile_level_val = kVTProfileLevel_H264_Baseline_AutoLevel ; break ;
case 0 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_AutoLevel ; break ;
case 13 : * profile_level_val = kVTProfileLevel_H264_Baseline_1_3 ; break ;
case 30 : * profile_level_val = kVTProfileLevel_H264_Baseline_3_0 ; break ;
case 31 : * profile_level_val = kVTProfileLevel_H264_Baseline_3_1 ; break ;
case 32 : * profile_level_val = kVTProfileLevel_H264_Baseline_3_2 ; break ;
case 40 : * profile_level_val = kVTProfileLevel_H264_Baseline_4_0 ; break ;
case 40 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_4_0 ; break ;
case 41 : * profile_level_val = kVTProfileLevel_H264_Baseline_4_1 ; break ;
case 42 : * profile_level_val = kVTProfileLevel_H264_Baseline_4_2 ; break ;
case 50 : * profile_level_val = kVTProfileLevel_H264_Baseline_5_0 ; break ;
case 51 : * profile_level_val = kVTProfileLevel_H264_Baseline_5_1 ; break ;
case 52 : * profile_level_val = kVTProfileLevel_H264_Baseline_5_2 ; break ;
case 42 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_4_2 ; break ;
case 50 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_5_0 ; break ;
case 51 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_5_1 ; break ;
case 52 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Baseline_5_2 ; break ;
}
break ;
case H264_PROF_MAIN :
switch ( vtctx - > level ) {
case 0 : * profile_level_val = kVTProfileLevel_H264_Main_AutoLevel ; break ;
case 0 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Main_AutoLevel ; break ;
case 30 : * profile_level_val = kVTProfileLevel_H264_Main_3_0 ; break ;
case 31 : * profile_level_val = kVTProfileLevel_H264_Main_3_1 ; break ;
case 32 : * profile_level_val = kVTProfileLevel_H264_Main_3_2 ; break ;
case 40 : * profile_level_val = kVTProfileLevel_H264_Main_4_0 ; break ;
case 41 : * profile_level_val = kVTProfileLevel_H264_Main_4_1 ; break ;
case 42 : * profile_level_val = kVTProfileLevel_H264_Main_4_2 ; break ;
case 42 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Main_4_2 ; break ;
case 50 : * profile_level_val = kVTProfileLevel_H264_Main_5_0 ; break ;
case 51 : * profile_level_val = kVTProfileLevel_H264_Main_5_1 ; break ;
case 52 : * profile_level_val = kVTProfileLevel_H264_Main_5_2 ; break ;
case 51 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Main_5_1 ; break ;
case 52 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_Main_5_2 ; break ;
}
break ;
case H264_PROF_HIGH :
switch ( vtctx - > level ) {
case 0 : * profile_level_val = kVTProfileLevel_H264_High_AutoLevel ; break ;
case 30 : * profile_level_val = kVTProfileLevel_H264_High_3_0 ; break ;
case 31 : * profile_level_val = kVTProfileLevel_H264_High_3_1 ; break ;
case 32 : * profile_level_val = kVTProfileLevel_H264_High_3_2 ; break ;
case 40 : * profile_level_val = kVTProfileLevel_H264_High_4_0 ; break ;
case 41 : * profile_level_val = kVTProfileLevel_H264_High_4_1 ; break ;
case 42 : * profile_level_val = kVTProfileLevel_H264_High_4_2 ; break ;
case 0 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_AutoLevel ; break ;
case 30 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_3_0 ; break ;
case 31 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_3_1 ; break ;
case 32 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_3_2 ; break ;
case 40 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_4_0 ; break ;
case 41 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_4_1 ; break ;
case 42 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_4_2 ; break ;
case 50 : * profile_level_val = kVTProfileLevel_H264_High_5_0 ; break ;
case 51 : * profile_level_val = kVTProfileLevel_H264_High_5_1 ; break ;
case 52 : * profile_level_val = kVTProfileLevel_H264_High_5_2 ; break ;
case 51 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_5_1 ; break ;
case 52 : * profile_level_val =
compat_keys . kVTProfileLevel_H264_High_5_2 ; break ;
}
break ;
}
@ -701,7 +799,7 @@ static int get_cv_color_primaries(AVCodecContext *avctx,
break ;
case AVCOL_PRI_BT2020 :
* primaries = kCVImageBufferColorPrimaries_ITU_R_2020 ;
* primaries = compat_keys . kCVImageBufferColorPrimaries_ITU_R_2020 ;
break ;
default :
@ -748,7 +846,7 @@ static int get_cv_transfer_function(AVCodecContext *avctx,
case AVCOL_TRC_BT2020_10 :
case AVCOL_TRC_BT2020_12 :
* transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2020 ;
* transfer_fnc = compat_keys . kCVImageBufferTransferFunction_ITU_R_2020 ;
break ;
default :
@ -779,7 +877,7 @@ static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) {
break ;
case AVCOL_SPC_BT2020_NCL :
* matrix = kCVImageBufferYCbCrMatrix_ITU_R_2020 ;
* matrix = compat_keys . kCVImageBufferYCbCrMatrix_ITU_R_2020 ;
break ;
default :
@ -846,7 +944,6 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
profile_level ) ;
if ( status ) {
av_log ( avctx , AV_LOG_ERROR , " Error setting profile/level property: %d \n " , status ) ;
return AVERROR_EXTERNAL ;
}
}
@ -1012,22 +1109,21 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
if ( vtctx - > entropy ! = VT_ENTROPY_NOT_SET ) {
CFStringRef entropy = vtctx - > entropy = = VT_CABAC ?
kVTH264EntropyMode_CABAC :
kVTH264EntropyMode_CAVLC ;
compat_keys . kVTH264EntropyMode_CABAC :
compat_keys . kVTH264EntropyMode_CAVLC ;
status = VTSessionSetProperty ( vtctx - > session ,
kVTCompressionPropertyKey_H264EntropyMode ,
compat_keys . kVTCompressionPropertyKey_H264EntropyMode ,
entropy ) ;
if ( status ) {
av_log ( avctx , AV_LOG_ERROR , " Error setting entropy property: %d \n " , status ) ;
return AVERROR_EXTERNAL ;
}
}
if ( vtctx - > realtime ) {
status = VTSessionSetProperty ( vtctx - > session ,
kVTCompressionPropertyKey_RealTime ,
compat_keys . kVTCompressionPropertyKey_RealTime ,
kCFBooleanTrue ) ;
if ( status ) {
@ -1055,6 +1151,8 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
CFNumberRef gamma_level = NULL ;
int status ;
pthread_once ( & once_ctrl , loadVTEncSymbols ) ;
codec_type = get_cm_codec_type ( avctx - > codec_id ) ;
if ( ! codec_type ) {
av_log ( avctx , AV_LOG_ERROR , " Error: no mapping for AVCodecID %d \n " , avctx - > codec_id ) ;
@ -1087,9 +1185,13 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
# if !TARGET_OS_IPHONE
if ( ! vtctx - > allow_sw ) {
CFDictionarySetValue ( enc_info , kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder , kCFBooleanTrue ) ;
CFDictionarySetValue ( enc_info ,
compat_keys . kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder ,
kCFBooleanTrue ) ;
} else {
CFDictionarySetValue ( enc_info , kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder , kCFBooleanTrue ) ;
CFDictionarySetValue ( enc_info ,
compat_keys . kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder ,
kCFBooleanTrue ) ;
}
# endif