diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 0f8e0ed2d..a7156ff78 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -163,6 +163,7 @@ struct obs_core_video { uint32_t output_height; uint32_t base_width; uint32_t base_height; + float color_matrix[16]; struct obs_display main_display; }; diff --git a/libobs/obs-video.c b/libobs/obs-video.c index cdb2b41c6..b1686d9c0 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -131,16 +131,7 @@ static inline void render_output_texture(struct obs_core_video *video, gs_set_render_target(target, NULL); set_render_size(width, height); - /* TODO: replace with programmable code */ - const float mat_val[16] = - { - -0.100644f, -0.338572f, 0.439216f, 0.501961f, - 0.182586f, 0.614231f, 0.062007f, 0.062745f, - 0.439216f, -0.398942f, -0.040274f, 0.501961f, - 0.000000f, 0.000000f, 0.000000f, 1.000000f - }; - - gs_effect_set_val(matrix, mat_val, sizeof(mat_val)); + gs_effect_set_val(matrix, video->color_matrix, sizeof(float) * 16); gs_effect_set_texture(image, texture); gs_enable_blending(false); diff --git a/libobs/obs.c b/libobs/obs.c index effc539d9..f4057ef1a 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -17,6 +17,7 @@ #include +#include "graphics/matrix4.h" #include "callback/calldata.h" #include "obs.h" @@ -48,6 +49,8 @@ static inline void make_video_info(struct video_output_info *vi, vi->fps_den = ovi->fps_den; vi->width = ovi->output_width; vi->height = ovi->output_height; + vi->range = ovi->range; + vi->colorspace = ovi->colorspace; } #define PIXEL_SIZE 4 @@ -256,6 +259,28 @@ static int obs_init_graphics(struct obs_video_info *ovi) return success ? OBS_VIDEO_SUCCESS : OBS_VIDEO_FAIL; } +static inline void set_video_matrix(struct obs_core_video *video, + struct obs_video_info *ovi) +{ + struct matrix4 mat; + struct vec4 r_row; + + if (format_is_yuv(ovi->output_format)) { + video_format_get_parameters(ovi->colorspace, ovi->range, + (float*)&mat, NULL, NULL); + matrix4_inv(&mat, &mat); + + /* swap R and G */ + r_row = mat.x; + mat.x = mat.y; + mat.y = r_row; + } else { + matrix4_identity(&mat); + } + + memcpy(video->color_matrix, &mat, sizeof(float) * 16); +} + static int obs_init_video(struct obs_video_info *ovi) { struct obs_core_video *video = &obs->video; @@ -269,6 +294,8 @@ static int obs_init_video(struct obs_video_info *ovi) video->output_height = ovi->output_height; video->gpu_conversion = ovi->gpu_conversion; + set_video_matrix(video, ovi); + errorcode = video_output_open(&video->video, &vi); if (errorcode != VIDEO_OUTPUT_SUCCESS) { @@ -728,6 +755,9 @@ bool obs_get_video_info(struct obs_video_info *ovi) memset(ovi, 0, sizeof(struct obs_video_info)); ovi->base_width = video->base_width; ovi->base_height = video->base_height; + ovi->gpu_conversion= video->gpu_conversion; + ovi->colorspace = info->colorspace; + ovi->range = info->range; ovi->output_width = info->width; ovi->output_height = info->height; ovi->output_format = info->format; diff --git a/libobs/obs.h b/libobs/obs.h index 7f7388bb4..8b91091e4 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -159,6 +159,9 @@ struct obs_video_info { /** Use shaders to convert to different color formats */ bool gpu_conversion; + + enum video_colorspace colorspace; /**< YUV type (if YUV) */ + enum video_range_type range; /**< YUV range (if YUV) */ }; /** diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 6329f2a50..fae02016a 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -1352,6 +1352,8 @@ int OBSBasic::ResetVideo() ovi.output_height = (uint32_t)config_get_uint(basicConfig, "Video", "OutputCY"); ovi.output_format = VIDEO_FORMAT_NV12; + ovi.colorspace = VIDEO_CS_709; + ovi.range = VIDEO_RANGE_FULL; ovi.adapter = 0; ovi.gpu_conversion = true;