summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Kern <kernrj@gmail.com>2016-04-27 10:53:15 -0400
committerwm4 <nfxjfg@googlemail.com>2016-05-04 18:40:40 +0200
commitdc750194b6c9c3f95d33f03f6f7d1992a8a2f885 (patch)
treeb35519a9da7d9217b579a3d537d7af11267c7658
parentc356b6865d373642685a6b445341ebb37ecbcc91 (diff)
lavc/videotoolboxenc: Set colorimetry values
Signed-off-by: Rick Kern <kernrj@gmail.com>
-rwxr-xr-xconfigure5
-rw-r--r--libavcodec/videotoolboxenc.c209
2 files changed, 213 insertions, 1 deletions
diff --git a/configure b/configure
index 74fd2109d1..18c43765c6 100755
--- a/configure
+++ b/configure
@@ -2079,6 +2079,7 @@ CONFIG_EXTRA="
vp3dsp
vp56dsp
vp8dsp
+ vt_bt2020
wma_freqs
wmv2dsp
"
@@ -2742,7 +2743,8 @@ nvenc_hevc_encoder_deps="nvenc"
videotoolbox_deps="VideoToolbox_VideoToolbox_h"
videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo"
videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames"
-videotoolbox_encoder_suggest="vda_framework"
+videotoolbox_encoder_suggest="vda_framework vt_bt2020"
+vt_bt2020_deps="kCVImageBufferColorPrimaries_ITU_R_2020"
# demuxers / muxers
ac3_demuxer_select="ac3_parser"
@@ -5445,6 +5447,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
+enabled 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
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
index 4a40f3507f..57ea2b336f 100644
--- a/libavcodec/videotoolboxenc.c
+++ b/libavcodec/videotoolboxenc.c
@@ -33,6 +33,12 @@
#include "internal.h"
#include <pthread.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
+
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;
@@ -527,6 +536,28 @@ static int get_cv_pixel_format(AVCodecContext* avctx,
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)
{
@@ -580,6 +611,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;
@@ -592,6 +625,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;
@@ -602,6 +739,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);
@@ -811,6 +949,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_WARNING, "Could not set 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_WARNING, "Could not set 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_WARNING, "Could not set color primaries: %d\n", status);
+ }
+ }
+
+ if (!status && gamma_level) {
+ status = VTSessionSetProperty(vtctx->session,
+ kCVImageBufferGammaLevelKey,
+ gamma_level);
+
+ if (status) {
+ av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
+ }
+ }
+
if (!vtctx->has_b_frames) {
status = VTSessionSetProperty(vtctx->session,
kVTCompressionPropertyKey_AllowFrameReordering,
@@ -1375,9 +1556,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);
@@ -1468,6 +1658,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;
@@ -1605,6 +1799,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;
}