Signed-off-by: Rick Kern <ker...@gmail.com> --- configure | 3 + libavcodec/videotoolboxenc.c | 209 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+)
diff --git a/configure b/configure index 94a66d8..10d4bab 100755 --- a/configure +++ b/configure @@ -5425,6 +5425,7 @@ check_header vdpau/vdpau_x11.h check_header VideoDecodeAcceleration/VDADecoder.h check_header VideoToolbox/VideoToolbox.h check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox +check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferColorPrimaries_ITU_R_2020 -framework CoreVideo check_header windows.h check_header X11/extensions/XvMClib.h check_header asm/types.h @@ -5677,6 +5678,8 @@ enabled openssl && { use_pkg_config openssl openssl/ssl.h SSL_library_ die "ERROR: openssl not found"; } enabled qtkit_indev && { check_header_objcc QTKit/QTKit.h || disable qtkit_indev; } +enabled kCVImageBufferColorPrimaries_ITU_R_2020 && add_cppflags -DHAVE_VT_BT2020_KEYS + # libdc1394 check if enabled libdc1394; then { require_pkg_config libdc1394-2 dc1394/dc1394.h dc1394_new && diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 72743b5..7f5b216 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -33,6 +33,12 @@ #include "internal.h" #include <pthread.h> +#ifndef HAVE_VT_BT2020_KEYS +# 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 + typedef enum VT_H264Profile { H264_PROF_AUTO, H264_PROF_BASELINE, @@ -58,6 +64,9 @@ typedef struct BufNode { typedef struct VTEncContext { AVClass *class; VTCompressionSessionRef session; + CFStringRef ycbcr_matrix; + CFStringRef color_primaries; + CFStringRef transfer_function; pthread_mutex_t lock; pthread_cond_t cv_sample_sent; @@ -547,6 +556,28 @@ static int get_cv_pixel_format( return 0; } +static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) { + VTEncContext *vtctx = avctx->priv_data; + + if (vtctx->color_primaries) { + CFDictionarySetValue(dict, + kCVImageBufferColorPrimariesKey, + vtctx->color_primaries); + } + + if (vtctx->transfer_function) { + CFDictionarySetValue(dict, + kCVImageBufferTransferFunctionKey, + vtctx->transfer_function); + } + + if (vtctx->ycbcr_matrix) { + CFDictionarySetValue(dict, + kCVImageBufferYCbCrMatrixKey, + vtctx->ycbcr_matrix); + } +} + static int create_cv_pixel_buffer_info(AVCodecContext* avctx, CFMutableDictionaryRef* dict) { @@ -600,6 +631,8 @@ static int create_cv_pixel_buffer_info(AVCodecContext* avctx, height_num); vt_release_num(&height_num); + add_color_attr(avctx, pixel_buffer_info); + *dict = pixel_buffer_info; return 0; @@ -612,6 +645,110 @@ pbinfo_nomem: return AVERROR(ENOMEM); } +static int get_cv_color_primaries(AVCodecContext *avctx, + CFStringRef *primaries) +{ + enum AVColorPrimaries pri = avctx->color_primaries; + switch (pri) { + case AVCOL_PRI_UNSPECIFIED: + *primaries = NULL; + break; + + case AVCOL_PRI_BT709: + *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2; + break; + + case AVCOL_PRI_BT2020: + *primaries = kCVImageBufferColorPrimaries_ITU_R_2020; + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Color primaries %s is not supported.\n", av_color_primaries_name(pri)); + *primaries = NULL; + return -1; + } + + return 0; +} + +static int get_cv_transfer_function(AVCodecContext *avctx, + CFStringRef *transfer_fnc, + CFNumberRef *gamma_level) +{ + enum AVColorTransferCharacteristic trc = avctx->color_trc; + Float32 gamma; + *gamma_level = NULL; + + switch (trc) { + case AVCOL_TRC_UNSPECIFIED: + *transfer_fnc = NULL; + break; + + case AVCOL_TRC_BT709: + *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_709_2; + break; + + case AVCOL_TRC_SMPTE240M: + *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995; + break; + + case AVCOL_TRC_GAMMA22: + gamma = 2.2; + *transfer_fnc = kCVImageBufferTransferFunction_UseGamma; + *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); + break; + + case AVCOL_TRC_GAMMA28: + gamma = 2.8; + *transfer_fnc = kCVImageBufferTransferFunction_UseGamma; + *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); + break; + + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: + *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2020; + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc)); + return -1; + } + + return 0; +} + +static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) { + switch(avctx->colorspace) { + case AVCOL_SPC_BT709: + *matrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2; + break; + + case AVCOL_SPC_UNSPECIFIED: + *matrix = NULL; + break; + + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_SMPTE170M: + *matrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4; + break; + + case AVCOL_SPC_SMPTE240M: + *matrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; + break; + + case AVCOL_SPC_BT2020_NCL: + *matrix = kCVImageBufferYCbCrMatrix_ITU_R_2020; + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Color space %s is not supported.\n", av_color_space_name(avctx->colorspace)); + return -1; + } + + return 0; +} + + static av_cold int vtenc_init(AVCodecContext *avctx) { CFMutableDictionaryRef enc_info; @@ -622,6 +759,7 @@ static av_cold int vtenc_init(AVCodecContext *avctx) SInt32 bit_rate = avctx->bit_rate; CFNumberRef bit_rate_num; CFBooleanRef has_b_frames_cfbool; + CFNumberRef gamma_level; int status; codec_type = get_cm_codec_type(avctx->codec_id); @@ -819,6 +957,49 @@ static av_cold int vtenc_init(AVCodecContext *avctx) } } + status = get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level); + if (!status && vtctx->transfer_function) { + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_TransferFunction, + vtctx->transfer_function); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting transfer function: %d\n", status); + } + } + + status = get_cv_ycbcr_matrix(avctx, &vtctx->ycbcr_matrix); + if (!status && vtctx->ycbcr_matrix) { + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_YCbCrMatrix, + vtctx->ycbcr_matrix); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting ycbcr matrix: %d\n", status); + } + } + + status = get_cv_color_primaries(avctx, &vtctx->color_primaries); + if (!status && vtctx->color_primaries) { + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_ColorPrimaries, + vtctx->color_primaries); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting color primaries: %d\n", status); + } + } + + if (!status && gamma_level) { + status = VTSessionSetProperty(vtctx->session, + kCVImageBufferGammaLevelKey, + gamma_level); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting gamma level: %d\n", status); + } + } + if (!vtctx->has_b_frames) { status = VTSessionSetProperty(vtctx->session, kVTCompressionPropertyKey_AllowFrameReordering, @@ -1383,9 +1564,18 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, size_t strides[AV_NUM_DATA_POINTERS]; int status; size_t contiguous_buf_size; +#if TARGET_OS_IPHONE CVPixelBufferPoolRef pix_buf_pool; VTEncContext* vtctx = avctx->priv_data; +#else + CFMutableDictionaryRef pix_buf_attachments = CFDictionaryCreateMutable( + kCFAllocatorDefault, + 10, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (!pix_buf_attachments) return AVERROR(ENOMEM); +#endif if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) { av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX); @@ -1476,6 +1666,10 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, cv_img ); + add_color_attr(avctx, pix_buf_attachments); + CVBufferSetAttachments(*cv_img, pix_buf_attachments, kCVAttachmentMode_ShouldPropagate); + CFRelease(pix_buf_attachments); + if (status) { av_log(avctx, AV_LOG_ERROR, "Error: Could not create CVPixelBuffer: %d\n", status); return AVERROR_EXTERNAL; @@ -1613,6 +1807,21 @@ static av_cold int vtenc_close(AVCodecContext *avctx) CFRelease(vtctx->session); vtctx->session = NULL; + if (vtctx->color_primaries) { + CFRelease(vtctx->color_primaries); + vtctx->color_primaries = NULL; + } + + if (vtctx->transfer_function) { + CFRelease(vtctx->transfer_function); + vtctx->transfer_function = NULL; + } + + if (vtctx->ycbcr_matrix) { + CFRelease(vtctx->ycbcr_matrix); + vtctx->ycbcr_matrix = NULL; + } + return 0; } -- 2.7.4 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel