diff --git a/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c b/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c index 8148e0eab..a7063d858 100644 --- a/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c +++ b/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c @@ -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 = diff --git a/plugins/obs-ffmpeg/jim-nvenc.c b/plugins/obs-ffmpeg/jim-nvenc.c index 58561158b..097db6432 100644 --- a/plugins/obs-ffmpeg/jim-nvenc.c +++ b/plugins/obs-ffmpeg/jim-nvenc.c @@ -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; diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-mux.c b/plugins/obs-ffmpeg/obs-ffmpeg-mux.c index 72945c05b..1ff745d61 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-mux.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-mux.c @@ -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) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c index 142e14d2c..74480a797 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c @@ -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; diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 6c711f5ec..027be3120 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -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) { @@ -225,8 +227,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; @@ -1057,16 +1061,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) { diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.h b/plugins/obs-ffmpeg/obs-ffmpeg-output.h index adb4494f6..d5ecbb8f6 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.h +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.h @@ -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;