diff options
author | Rick Kern <kernrj@gmail.com> | 2017-02-23 00:05:01 -0500 |
---|---|---|
committer | Rick Kern <kernrj@gmail.com> | 2017-02-23 00:05:01 -0500 |
commit | dcd3418a35aab7ef283b68ed9997ce4ac204094e (patch) | |
tree | 5328472946e0e3859fe405d8c91920fa1a9ff028 | |
parent | 9568b2e425f127031ddc91dd78cb9b9f2cae206d (diff) | |
download | ffmpeg-dcd3418a35aab7ef283b68ed9997ce4ac204094e.tar.gz |
lavc/videotoolboxenc: check for dictionary key symbols
Fixes #6081. Some dictionary keys are not present on OS X 10.8.
This loads the symbols and uses a default value if not present.
Signed-off-by: Rick Kern <kernrj@gmail.com>
-rw-r--r-- | libavcodec/videotoolboxenc.c | 174 |
1 files changed, 138 insertions, 36 deletions
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index cb9e2fe6e8..fe64250f29 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -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 |