summaryrefslogtreecommitdiff
path: root/libavcodec/videotoolboxenc.c
diff options
context:
space:
mode:
authorRick Kern <kernrj@gmail.com>2017-02-23 00:05:01 -0500
committerRick Kern <kernrj@gmail.com>2017-02-23 00:05:01 -0500
commitdcd3418a35aab7ef283b68ed9997ce4ac204094e (patch)
tree5328472946e0e3859fe405d8c91920fa1a9ff028 /libavcodec/videotoolboxenc.c
parent9568b2e425f127031ddc91dd78cb9b9f2cae206d (diff)
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>
Diffstat (limited to 'libavcodec/videotoolboxenc.c')
-rw-r--r--libavcodec/videotoolboxenc.c174
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