Commit dc750194 authored by Rick Kern's avatar Rick Kern Committed by wm4

lavc/videotoolboxenc: Set colorimetry values

Signed-off-by: 's avatarRick Kern <kernrj@gmail.com>
parent c356b686
...@@ -2079,6 +2079,7 @@ CONFIG_EXTRA=" ...@@ -2079,6 +2079,7 @@ CONFIG_EXTRA="
vp3dsp vp3dsp
vp56dsp vp56dsp
vp8dsp vp8dsp
vt_bt2020
wma_freqs wma_freqs
wmv2dsp wmv2dsp
" "
...@@ -2742,7 +2743,8 @@ nvenc_hevc_encoder_deps="nvenc" ...@@ -2742,7 +2743,8 @@ nvenc_hevc_encoder_deps="nvenc"
videotoolbox_deps="VideoToolbox_VideoToolbox_h" videotoolbox_deps="VideoToolbox_VideoToolbox_h"
videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo" videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo"
videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames" 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 # demuxers / muxers
ac3_demuxer_select="ac3_parser" ac3_demuxer_select="ac3_parser"
...@@ -5445,6 +5447,7 @@ check_header vdpau/vdpau_x11.h ...@@ -5445,6 +5447,7 @@ check_header vdpau/vdpau_x11.h
check_header VideoDecodeAcceleration/VDADecoder.h check_header VideoDecodeAcceleration/VDADecoder.h
check_header VideoToolbox/VideoToolbox.h check_header VideoToolbox/VideoToolbox.h
check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox 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 windows.h
check_header X11/extensions/XvMClib.h check_header X11/extensions/XvMClib.h
check_header asm/types.h check_header asm/types.h
......
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
#include "internal.h" #include "internal.h"
#include <pthread.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 { typedef enum VT_H264Profile {
H264_PROF_AUTO, H264_PROF_AUTO,
H264_PROF_BASELINE, H264_PROF_BASELINE,
...@@ -58,6 +64,9 @@ typedef struct BufNode { ...@@ -58,6 +64,9 @@ typedef struct BufNode {
typedef struct VTEncContext { typedef struct VTEncContext {
AVClass *class; AVClass *class;
VTCompressionSessionRef session; VTCompressionSessionRef session;
CFStringRef ycbcr_matrix;
CFStringRef color_primaries;
CFStringRef transfer_function;
pthread_mutex_t lock; pthread_mutex_t lock;
pthread_cond_t cv_sample_sent; pthread_cond_t cv_sample_sent;
...@@ -527,6 +536,28 @@ static int get_cv_pixel_format(AVCodecContext* avctx, ...@@ -527,6 +536,28 @@ static int get_cv_pixel_format(AVCodecContext* avctx,
return 0; 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, static int create_cv_pixel_buffer_info(AVCodecContext* avctx,
CFMutableDictionaryRef* dict) CFMutableDictionaryRef* dict)
{ {
...@@ -580,6 +611,8 @@ static int create_cv_pixel_buffer_info(AVCodecContext* avctx, ...@@ -580,6 +611,8 @@ static int create_cv_pixel_buffer_info(AVCodecContext* avctx,
height_num); height_num);
vt_release_num(&height_num); vt_release_num(&height_num);
add_color_attr(avctx, pixel_buffer_info);
*dict = pixel_buffer_info; *dict = pixel_buffer_info;
return 0; return 0;
...@@ -592,6 +625,110 @@ pbinfo_nomem: ...@@ -592,6 +625,110 @@ pbinfo_nomem:
return AVERROR(ENOMEM); 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) static av_cold int vtenc_init(AVCodecContext *avctx)
{ {
CFMutableDictionaryRef enc_info; CFMutableDictionaryRef enc_info;
...@@ -602,6 +739,7 @@ static av_cold int vtenc_init(AVCodecContext *avctx) ...@@ -602,6 +739,7 @@ static av_cold int vtenc_init(AVCodecContext *avctx)
SInt32 bit_rate = avctx->bit_rate; SInt32 bit_rate = avctx->bit_rate;
CFNumberRef bit_rate_num; CFNumberRef bit_rate_num;
CFBooleanRef has_b_frames_cfbool; CFBooleanRef has_b_frames_cfbool;
CFNumberRef gamma_level;
int status; int status;
codec_type = get_cm_codec_type(avctx->codec_id); codec_type = get_cm_codec_type(avctx->codec_id);
...@@ -811,6 +949,49 @@ static av_cold int vtenc_init(AVCodecContext *avctx) ...@@ -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) { if (!vtctx->has_b_frames) {
status = VTSessionSetProperty(vtctx->session, status = VTSessionSetProperty(vtctx->session,
kVTCompressionPropertyKey_AllowFrameReordering, kVTCompressionPropertyKey_AllowFrameReordering,
...@@ -1375,9 +1556,18 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, ...@@ -1375,9 +1556,18 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx,
size_t strides[AV_NUM_DATA_POINTERS]; size_t strides[AV_NUM_DATA_POINTERS];
int status; int status;
size_t contiguous_buf_size; size_t contiguous_buf_size;
#if TARGET_OS_IPHONE
CVPixelBufferPoolRef pix_buf_pool; CVPixelBufferPoolRef pix_buf_pool;
VTEncContext* vtctx = avctx->priv_data; 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) { if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX); av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX);
...@@ -1468,6 +1658,10 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, ...@@ -1468,6 +1658,10 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx,
cv_img cv_img
); );
add_color_attr(avctx, pix_buf_attachments);
CVBufferSetAttachments(*cv_img, pix_buf_attachments, kCVAttachmentMode_ShouldPropagate);
CFRelease(pix_buf_attachments);
if (status) { if (status) {
av_log(avctx, AV_LOG_ERROR, "Error: Could not create CVPixelBuffer: %d\n", status); av_log(avctx, AV_LOG_ERROR, "Error: Could not create CVPixelBuffer: %d\n", status);
return AVERROR_EXTERNAL; return AVERROR_EXTERNAL;
...@@ -1605,6 +1799,21 @@ static av_cold int vtenc_close(AVCodecContext *avctx) ...@@ -1605,6 +1799,21 @@ static av_cold int vtenc_close(AVCodecContext *avctx)
CFRelease(vtctx->session); CFRelease(vtctx->session);
vtctx->session = NULL; 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; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment