From 065379bffa132eb66a3a89441e9c4011d5cdea2d Mon Sep 17 00:00:00 2001 From: Palana Date: Thu, 24 Apr 2014 00:24:51 +0200 Subject: [PATCH] Add limited range rendering for rendering YUV non-full range sources --- build/data/libobs/default.effect | 3 +++ libobs/obs-internal.h | 3 +++ libobs/obs-source.c | 46 ++++++++++++++++++++++++++------ libobs/obs.h | 3 +++ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/build/data/libobs/default.effect b/build/data/libobs/default.effect index e5ad2b3fb..217eeeebb 100644 --- a/build/data/libobs/default.effect +++ b/build/data/libobs/default.effect @@ -1,5 +1,7 @@ uniform float4x4 ViewProj; uniform float4x4 color_matrix; +uniform float3 color_range_min; +uniform float3 color_range_max; uniform texture2d image; sampler_state def_sampler { @@ -29,6 +31,7 @@ float4 PSDrawBare(VertInOut vert_in) : TARGET float4 PSDrawMatrix(VertInOut vert_in) : TARGET { float4 yuv = image.Sample(def_sampler, vert_in.uv); + yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); return saturate(mul(float4(yuv.xyz, 1.0), color_matrix)); } diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 40185684e..2edbe0ec1 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -269,6 +269,9 @@ struct obs_source { texture_t async_texture; enum video_format async_format; float async_color_matrix[16]; + bool async_full_range; + float async_color_range_min[3]; + float async_color_range_max[3]; bool async_flip; DARRAY(struct source_frame*) video_frames; pthread_mutex_t video_mutex; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 8037208d3..c66124709 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -625,10 +625,15 @@ static bool update_async_texture(struct obs_source *source, void *ptr; uint32_t linesize; - source->async_format = frame->format; - source->async_flip = frame->flip; + source->async_format = frame->format; + source->async_flip = frame->flip; + source->async_full_range = frame->full_range; memcpy(source->async_color_matrix, frame->color_matrix, sizeof(frame->color_matrix)); + memcpy(source->async_color_range_min, frame->color_range_min, + sizeof frame->color_range_min); + memcpy(source->async_color_range_max, frame->color_range_max, + sizeof frame->color_range_max); if (type == CONVERT_NONE) { texture_setimage(tex, frame->data[0], frame->linesize[0], @@ -661,13 +666,29 @@ static bool update_async_texture(struct obs_source *source, return true; } +static float const full_range_min[] = {0., 0., 0.}; +static float const full_range_max[] = {1., 1., 1.}; + static inline void obs_source_draw_texture(struct obs_source *source, - effect_t effect, float *color_matrix) + effect_t effect, float *color_matrix, + float const *color_range_min, float const *color_range_max) { texture_t tex = source->async_texture; eparam_t param; if (color_matrix) { + size_t const size = sizeof(float) * 3; + + if (!color_range_min) + color_range_min = full_range_min; + if (!color_range_max) + color_range_max = full_range_max; + + param = effect_getparambyname(effect, "color_range_min"); + effect_setval(effect, param, color_range_min, size); + param = effect_getparambyname(effect, "color_range_max"); + effect_setval(effect, param, color_range_max, size); + param = effect_getparambyname(effect, "color_matrix"); effect_setval(effect, param, color_matrix, sizeof(float) * 16); } @@ -680,10 +701,11 @@ static inline void obs_source_draw_texture(struct obs_source *source, static void obs_source_draw_async_texture(struct obs_source *source) { - effect_t effect = gs_geteffect(); - bool yuv = format_is_yuv(source->async_format); - const char *type = yuv ? "DrawMatrix" : "Draw"; - bool def_draw = (!effect); + effect_t effect = gs_geteffect(); + bool yuv = format_is_yuv(source->async_format); + bool limited_range = yuv && !source->async_full_range; + const char *type = yuv ? "DrawMatrix" : "Draw"; + bool def_draw = (!effect); technique_t tech; if (def_draw) { @@ -694,7 +716,9 @@ static void obs_source_draw_async_texture(struct obs_source *source) } obs_source_draw_texture(source, effect, - yuv ? source->async_color_matrix : NULL); + yuv ? source->async_color_matrix : NULL, + limited_range ? source->async_color_range_min : NULL, + limited_range ? source->async_color_range_max : NULL); if (def_draw) { technique_endpass(tech); @@ -947,8 +971,14 @@ static void copy_frame_data(struct source_frame *dst, const struct source_frame *src) { dst->flip = src->flip; + dst->full_range = src->full_range; dst->timestamp = src->timestamp; memcpy(dst->color_matrix, src->color_matrix, sizeof(float) * 16); + if (!dst->full_range) { + size_t const size = sizeof(float) * 3; + memcpy(dst->color_range_min, src->color_range_min, size); + memcpy(dst->color_range_max, src->color_range_max, size); + } switch (dst->format) { case VIDEO_FORMAT_I420: diff --git a/libobs/obs.h b/libobs/obs.h index 010392efb..4f59b7709 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -166,6 +166,9 @@ struct source_frame { enum video_format format; float color_matrix[16]; + bool full_range; + float color_range_min[3]; + float color_range_max[3]; bool flip; }; -- GitLab