summaryrefslogtreecommitdiff
path: root/libavcodec/videotoolboxenc.c
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 /libavcodec/videotoolboxenc.c
parentc356b6865d373642685a6b445341ebb37ecbcc91 (diff)
lavc/videotoolboxenc: Set colorimetry values
Signed-off-by: Rick Kern <kernrj@gmail.com>
Diffstat (limited to 'libavcodec/videotoolboxenc.c')
-rw-r--r--libavcodec/videotoolboxenc.c209
1 files changed, 209 insertions, 0 deletions
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;
}