mirror of https://git.ffmpeg.org/ffmpeg.git
lavc/videotoolboxenc: Set colorimetry values
Signed-off-by: Rick Kern <kernrj@gmail.com>
This commit is contained in:
parent
c356b6865d
commit
dc750194b6
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue