Merge pull request #2356 from jpark37/sycc-color-space
Color space refinements
This commit is contained in:
commit
bfdf5dc947
@ -4809,6 +4809,11 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="colorSpace">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">sRGB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">709</string>
|
||||
|
@ -1383,7 +1383,7 @@ bool OBSBasic::InitBasicConfigDefaults()
|
||||
config_set_default_uint(basicConfig, "Video", "FPSDen", 1);
|
||||
config_set_default_string(basicConfig, "Video", "ScaleType", "bicubic");
|
||||
config_set_default_string(basicConfig, "Video", "ColorFormat", "NV12");
|
||||
config_set_default_string(basicConfig, "Video", "ColorSpace", "601");
|
||||
config_set_default_string(basicConfig, "Video", "ColorSpace", "sRGB");
|
||||
config_set_default_string(basicConfig, "Video", "ColorRange",
|
||||
"Partial");
|
||||
|
||||
@ -3792,8 +3792,11 @@ int OBSBasic::ResetVideo()
|
||||
ovi.output_height =
|
||||
(uint32_t)config_get_uint(basicConfig, "Video", "OutputCY");
|
||||
ovi.output_format = GetVideoFormatFromName(colorFormat);
|
||||
ovi.colorspace = astrcmpi(colorSpace, "601") == 0 ? VIDEO_CS_601
|
||||
: VIDEO_CS_709;
|
||||
ovi.colorspace = astrcmpi(colorSpace, "601") == 0
|
||||
? VIDEO_CS_601
|
||||
: (astrcmpi(colorSpace, "709") == 0
|
||||
? VIDEO_CS_709
|
||||
: VIDEO_CS_SRGB);
|
||||
ovi.range = astrcmpi(colorRange, "Full") == 0 ? VIDEO_RANGE_FULL
|
||||
: VIDEO_RANGE_PARTIAL;
|
||||
ovi.adapter =
|
||||
|
12
deps/media-playback/media-playback/media.c
vendored
12
deps/media-playback/media-playback/media.c
vendored
@ -109,9 +109,15 @@ static inline enum speaker_layout convert_speaker_layout(uint8_t channels)
|
||||
}
|
||||
}
|
||||
|
||||
static inline enum video_colorspace convert_color_space(enum AVColorSpace s)
|
||||
static inline enum video_colorspace
|
||||
convert_color_space(enum AVColorSpace s, enum AVColorTransferCharacteristic trc)
|
||||
{
|
||||
return s == AVCOL_SPC_BT709 ? VIDEO_CS_709 : VIDEO_CS_DEFAULT;
|
||||
if (s == AVCOL_SPC_BT709) {
|
||||
return (trc == AVCOL_TRC_IEC61966_2_1) ? VIDEO_CS_SRGB
|
||||
: VIDEO_CS_709;
|
||||
}
|
||||
|
||||
return VIDEO_CS_DEFAULT;
|
||||
}
|
||||
|
||||
static inline enum video_range_type convert_color_range(enum AVColorRange r)
|
||||
@ -372,7 +378,7 @@ static void mp_media_next_video(mp_media_t *m, bool preload)
|
||||
frame->data[0] -= frame->linesize[0] * (f->height - 1);
|
||||
|
||||
new_format = convert_pixel_format(m->scale_format);
|
||||
new_space = convert_color_space(f->colorspace);
|
||||
new_space = convert_color_space(f->colorspace, f->color_trc);
|
||||
new_range = m->force_range == VIDEO_RANGE_DEFAULT
|
||||
? convert_color_range(f->color_range)
|
||||
: m->force_range;
|
||||
|
@ -176,9 +176,10 @@ static inline const char *get_video_colorspace_name(enum video_colorspace cs)
|
||||
switch (cs) {
|
||||
case VIDEO_CS_709:
|
||||
return "709";
|
||||
case VIDEO_CS_SRGB:
|
||||
return "sRGB";
|
||||
case VIDEO_CS_601:
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_SRGB:;
|
||||
case VIDEO_CS_DEFAULT:;
|
||||
}
|
||||
|
||||
return "601";
|
||||
|
@ -173,6 +173,8 @@ bool video_format_get_parameters(enum video_colorspace color_space,
|
||||
#endif
|
||||
if (color_space == VIDEO_CS_DEFAULT)
|
||||
color_space = VIDEO_CS_601;
|
||||
else if (color_space == VIDEO_CS_SRGB)
|
||||
color_space = VIDEO_CS_709;
|
||||
|
||||
for (size_t i = 0; i < NUM_FORMATS; i++) {
|
||||
if (format_info[i].color_space != color_space)
|
||||
|
@ -92,12 +92,11 @@ static inline int get_ffmpeg_scale_type(enum video_scale_type type)
|
||||
static inline const int *get_ffmpeg_coeffs(enum video_colorspace cs)
|
||||
{
|
||||
switch (cs) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
return sws_getCoefficients(SWS_CS_ITU601);
|
||||
case VIDEO_CS_601:
|
||||
return sws_getCoefficients(SWS_CS_ITU601);
|
||||
case VIDEO_CS_709:
|
||||
case VIDEO_CS_SRGB:
|
||||
return sws_getCoefficients(SWS_CS_ITU709);
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
default:
|
||||
return sws_getCoefficients(SWS_CS_ITU601);
|
||||
}
|
||||
|
@ -79,6 +79,10 @@ struct main_params {
|
||||
int height;
|
||||
int fps_num;
|
||||
int fps_den;
|
||||
int color_primaries;
|
||||
int color_trc;
|
||||
int colorspace;
|
||||
int color_range;
|
||||
char *acodec;
|
||||
char *muxer_settings;
|
||||
};
|
||||
@ -249,6 +253,18 @@ static bool init_params(int *argc, char ***argv, struct main_params *params,
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->height, "video height"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->color_primaries,
|
||||
"video color primaries"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->color_trc,
|
||||
"video color trc"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->colorspace,
|
||||
"video colorspace"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->color_range,
|
||||
"video color range"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->fps_num, "video fps num"))
|
||||
return false;
|
||||
if (!get_opt_int(argc, argv, ¶ms->fps_den, "video fps den"))
|
||||
@ -327,6 +343,10 @@ static void create_video_stream(struct ffmpeg_mux *ffm)
|
||||
context->height = ffm->params.height;
|
||||
context->coded_width = ffm->params.width;
|
||||
context->coded_height = ffm->params.height;
|
||||
context->color_primaries = ffm->params.color_primaries;
|
||||
context->color_trc = ffm->params.color_trc;
|
||||
context->colorspace = ffm->params.colorspace;
|
||||
context->color_range = ffm->params.color_range;
|
||||
context->extradata = extradata;
|
||||
context->extradata_size = ffm->video_header.size;
|
||||
context->time_base =
|
||||
|
@ -429,9 +429,25 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
|
||||
vui_params->videoSignalTypePresentFlag = 1;
|
||||
vui_params->videoFullRangeFlag = (voi->range == VIDEO_RANGE_FULL);
|
||||
vui_params->colourDescriptionPresentFlag = 1;
|
||||
vui_params->colourMatrix = (voi->colorspace == VIDEO_CS_709) ? 1 : 5;
|
||||
vui_params->colourPrimaries = 1;
|
||||
vui_params->transferCharacteristics = 1;
|
||||
|
||||
switch (voi->colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
vui_params->colourPrimaries = 6;
|
||||
vui_params->transferCharacteristics = 6;
|
||||
vui_params->colourMatrix = 6;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
vui_params->colourPrimaries = 1;
|
||||
vui_params->transferCharacteristics = 1;
|
||||
vui_params->colourMatrix = 1;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
vui_params->colourPrimaries = 1;
|
||||
vui_params->transferCharacteristics = 13;
|
||||
vui_params->colourMatrix = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
enc->bframes = bf > 0;
|
||||
|
||||
|
@ -156,10 +156,37 @@ static void add_video_encoder_params(struct ffmpeg_muxer *stream,
|
||||
|
||||
obs_data_release(settings);
|
||||
|
||||
dstr_catf(cmd, "%s %d %d %d %d %d ", obs_encoder_get_codec(vencoder),
|
||||
bitrate, obs_output_get_width(stream->output),
|
||||
obs_output_get_height(stream->output), (int)info->fps_num,
|
||||
(int)info->fps_den);
|
||||
enum AVColorPrimaries pri = AVCOL_PRI_UNSPECIFIED;
|
||||
enum AVColorTransferCharacteristic trc = AVCOL_TRC_UNSPECIFIED;
|
||||
enum AVColorSpace spc = AVCOL_SPC_UNSPECIFIED;
|
||||
switch (info->colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
pri = AVCOL_PRI_SMPTE170M;
|
||||
trc = AVCOL_TRC_SMPTE170M;
|
||||
spc = AVCOL_SPC_SMPTE170M;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
pri = AVCOL_PRI_BT709;
|
||||
trc = AVCOL_TRC_BT709;
|
||||
spc = AVCOL_SPC_BT709;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
pri = AVCOL_PRI_BT709;
|
||||
trc = AVCOL_TRC_IEC61966_2_1;
|
||||
spc = AVCOL_SPC_BT709;
|
||||
break;
|
||||
}
|
||||
|
||||
const enum AVColorRange range = (info->range == VIDEO_RANGE_FULL)
|
||||
? AVCOL_RANGE_JPEG
|
||||
: AVCOL_RANGE_MPEG;
|
||||
|
||||
dstr_catf(cmd, "%s %d %d %d %d %d %d %d %d %d ",
|
||||
obs_encoder_get_codec(vencoder), bitrate,
|
||||
obs_output_get_width(stream->output),
|
||||
obs_output_get_height(stream->output), (int)pri, (int)trc,
|
||||
(int)spc, (int)range, (int)info->fps_num, (int)info->fps_den);
|
||||
}
|
||||
|
||||
static void add_audio_encoder_params(struct dstr *cmd, obs_encoder_t *aencoder)
|
||||
|
@ -235,14 +235,30 @@ static bool nvenc_update(void *data, obs_data_t *settings)
|
||||
enc->context->height = obs_encoder_get_height(enc->encoder);
|
||||
enc->context->time_base = (AVRational){voi->fps_den, voi->fps_num};
|
||||
enc->context->pix_fmt = obs_to_ffmpeg_video_format(info.format);
|
||||
enc->context->colorspace = info.colorspace == VIDEO_CS_709
|
||||
? AVCOL_SPC_BT709
|
||||
: AVCOL_SPC_BT470BG;
|
||||
enc->context->color_range = info.range == VIDEO_RANGE_FULL
|
||||
? AVCOL_RANGE_JPEG
|
||||
: AVCOL_RANGE_MPEG;
|
||||
enc->context->max_b_frames = bf;
|
||||
|
||||
switch (info.colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
enc->context->color_trc = AVCOL_TRC_SMPTE170M;
|
||||
enc->context->color_primaries = AVCOL_PRI_SMPTE170M;
|
||||
enc->context->colorspace = AVCOL_SPC_SMPTE170M;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
enc->context->color_trc = AVCOL_TRC_BT709;
|
||||
enc->context->color_primaries = AVCOL_PRI_BT709;
|
||||
enc->context->colorspace = AVCOL_SPC_BT709;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
enc->context->color_trc = AVCOL_TRC_IEC61966_2_1;
|
||||
enc->context->color_primaries = AVCOL_PRI_BT709;
|
||||
enc->context->colorspace = AVCOL_SPC_BT709;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyint_sec)
|
||||
enc->context->gop_size =
|
||||
keyint_sec * voi->fps_num / voi->fps_den;
|
||||
|
@ -169,8 +169,10 @@ static bool open_video_codec(struct ffmpeg_data *data)
|
||||
data->vframe->format = context->pix_fmt;
|
||||
data->vframe->width = context->width;
|
||||
data->vframe->height = context->height;
|
||||
data->vframe->colorspace = data->config.color_space;
|
||||
data->vframe->color_range = data->config.color_range;
|
||||
data->vframe->color_primaries = data->config.color_primaries;
|
||||
data->vframe->color_trc = data->config.color_trc;
|
||||
data->vframe->colorspace = data->config.colorspace;
|
||||
|
||||
ret = av_frame_get_buffer(data->vframe, base_get_alignment());
|
||||
if (ret < 0) {
|
||||
@ -233,8 +235,10 @@ static bool create_video_stream(struct ffmpeg_data *data)
|
||||
context->time_base = (AVRational){ovi.fps_den, ovi.fps_num};
|
||||
context->gop_size = data->config.gop_size;
|
||||
context->pix_fmt = closest_format;
|
||||
context->colorspace = data->config.color_space;
|
||||
context->color_range = data->config.color_range;
|
||||
context->color_primaries = data->config.color_primaries;
|
||||
context->color_trc = data->config.color_trc;
|
||||
context->colorspace = data->config.colorspace;
|
||||
context->thread_count = 0;
|
||||
|
||||
data->video->time_base = context->time_base;
|
||||
@ -1081,16 +1085,39 @@ static bool try_connect(struct ffmpeg_output *output)
|
||||
config.audio_tracks = (int)obs_output_get_mixers(output->output);
|
||||
config.audio_mix_count = get_audio_mix_count(config.audio_tracks);
|
||||
|
||||
config.color_range = voi->range == VIDEO_RANGE_FULL ? AVCOL_RANGE_JPEG
|
||||
: AVCOL_RANGE_MPEG;
|
||||
switch (voi->colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
config.color_primaries = AVCOL_PRI_SMPTE170M;
|
||||
config.color_trc = AVCOL_TRC_SMPTE170M;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
config.color_primaries = AVCOL_PRI_BT709;
|
||||
config.color_trc = AVCOL_TRC_BT709;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
config.color_primaries = AVCOL_PRI_BT709;
|
||||
config.color_trc = AVCOL_TRC_IEC61966_2_1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (format_is_yuv(voi->format)) {
|
||||
config.color_range = voi->range == VIDEO_RANGE_FULL
|
||||
? AVCOL_RANGE_JPEG
|
||||
: AVCOL_RANGE_MPEG;
|
||||
config.color_space = voi->colorspace == VIDEO_CS_709
|
||||
? AVCOL_SPC_BT709
|
||||
: AVCOL_SPC_BT470BG;
|
||||
switch (voi->colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
config.colorspace = AVCOL_SPC_SMPTE170M;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
config.colorspace = AVCOL_SPC_BT709;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
config.colorspace = AVCOL_SPC_BT709;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
config.color_range = AVCOL_RANGE_UNSPECIFIED;
|
||||
config.color_space = AVCOL_SPC_RGB;
|
||||
config.colorspace = AVCOL_SPC_RGB;
|
||||
}
|
||||
|
||||
if (config.format == AV_PIX_FMT_NONE) {
|
||||
|
@ -23,7 +23,9 @@ struct ffmpeg_cfg {
|
||||
int audio_tracks;
|
||||
enum AVPixelFormat format;
|
||||
enum AVColorRange color_range;
|
||||
enum AVColorSpace color_space;
|
||||
enum AVColorPrimaries color_primaries;
|
||||
enum AVColorTransferCharacteristic color_trc;
|
||||
enum AVColorSpace colorspace;
|
||||
int scale_width;
|
||||
int scale_height;
|
||||
int width;
|
||||
|
@ -362,23 +362,9 @@ static void log_x264(void *param, int level, const char *format, va_list args)
|
||||
UNUSED_PARAMETER(level);
|
||||
}
|
||||
|
||||
static inline const char *get_x264_colorspace_name(enum video_colorspace cs)
|
||||
{
|
||||
switch (cs) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
case VIDEO_CS_SRGB:
|
||||
return "undef";
|
||||
case VIDEO_CS_709:;
|
||||
}
|
||||
|
||||
return "bt709";
|
||||
}
|
||||
|
||||
static inline int get_x264_cs_val(enum video_colorspace cs,
|
||||
static inline int get_x264_cs_val(const char *const name,
|
||||
const char *const names[])
|
||||
{
|
||||
const char *name = get_x264_colorspace_name(cs);
|
||||
int idx = 0;
|
||||
do {
|
||||
if (strcmp(names[idx], name) == 0)
|
||||
@ -481,13 +467,38 @@ static void update_params(struct obs_x264 *obsx264, obs_data_t *settings,
|
||||
if (obs_data_has_user_value(settings, "bf"))
|
||||
obsx264->params.i_bframe = bf;
|
||||
|
||||
obsx264->params.vui.i_transfer =
|
||||
get_x264_cs_val(info.colorspace, x264_transfer_names);
|
||||
obsx264->params.vui.i_colmatrix =
|
||||
get_x264_cs_val(info.colorspace, x264_colmatrix_names);
|
||||
obsx264->params.vui.i_colorprim =
|
||||
get_x264_cs_val(info.colorspace, x264_colorprim_names);
|
||||
static const char *const smpte170m = "smpte170m";
|
||||
static const char *const bt709 = "bt709";
|
||||
static const char *const iec61966_2_1 = "iec61966-2-1";
|
||||
const char *colorprim = NULL;
|
||||
const char *transfer = NULL;
|
||||
const char *colmatrix = NULL;
|
||||
switch (info.colorspace) {
|
||||
case VIDEO_CS_DEFAULT:
|
||||
case VIDEO_CS_601:
|
||||
colorprim = smpte170m;
|
||||
transfer = smpte170m;
|
||||
colmatrix = smpte170m;
|
||||
break;
|
||||
case VIDEO_CS_709:
|
||||
colorprim = bt709;
|
||||
transfer = bt709;
|
||||
colmatrix = bt709;
|
||||
break;
|
||||
case VIDEO_CS_SRGB:
|
||||
colorprim = bt709;
|
||||
transfer = iec61966_2_1;
|
||||
colmatrix = bt709;
|
||||
break;
|
||||
}
|
||||
|
||||
obsx264->params.vui.b_fullrange = info.range == VIDEO_RANGE_FULL;
|
||||
obsx264->params.vui.i_colorprim =
|
||||
get_x264_cs_val(colorprim, x264_colorprim_names);
|
||||
obsx264->params.vui.i_transfer =
|
||||
get_x264_cs_val(transfer, x264_transfer_names);
|
||||
obsx264->params.vui.i_colmatrix =
|
||||
get_x264_cs_val(colmatrix, x264_colmatrix_names);
|
||||
|
||||
/* use the new filler method for CBR to allow real-time adjusting of
|
||||
* the bitrate */
|
||||
|
Loading…
x
Reference in New Issue
Block a user