From 817a724deab313e91d4daf2255280bad4dbddd77 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Thu, 18 Dec 2014 11:37:46 -0800 Subject: [PATCH] libobs: Add NV12_Reverse shader --- libobs/data/format_conversion.effect | 34 ++++++++++++++++++++++++++++ libobs/obs-source.c | 21 +++++++++++++---- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/libobs/data/format_conversion.effect b/libobs/data/format_conversion.effect index 8a77cec01..e58996003 100644 --- a/libobs/data/format_conversion.effect +++ b/libobs/data/format_conversion.effect @@ -254,6 +254,31 @@ float4 PSPlanar420_Reverse(VertInOut vert_in) : TARGET ); } +float4 PSNV12_Reverse(VertInOut vert_in) : TARGET +{ + float x = vert_in.uv.x; + float y = vert_in.uv.y; +#ifdef _OPENGL + y = 1. - y; +#endif + float x_offset = floor(x * width + PRECISION_OFFSET); + float y_offset = floor(y * height + PRECISION_OFFSET); + + float lum_offset = y_offset * width + x_offset + PRECISION_OFFSET; + lum_offset = floor(lum_offset); + + float ch_offset = floor(y_offset * 0.5 + PRECISION_OFFSET) * width_d2 + + (x_offset * 0.5); + ch_offset = floor(ch_offset * 2.0 + PRECISION_OFFSET); + + return float4( + GetOffsetColor(lum_offset), + GetOffsetColor(u_plane_offset + ch_offset), + GetOffsetColor(u_plane_offset + ch_offset + 1.0), + 1.0 + ); +} + technique Planar420 { pass @@ -307,3 +332,12 @@ technique I420_Reverse pixel_shader = PSPlanar420_Reverse(vert_in); } } + +technique NV12_Reverse +{ + pass + { + vertex_shader = VSDefault(vert_in); + pixel_shader = PSNV12_Reverse(vert_in); + } +} diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 37df484f1..7e258a2b5 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -799,6 +799,19 @@ static inline bool set_planar420_sizes(struct obs_source *source, return true; } +static inline bool set_nv12_sizes(struct obs_source *source, + struct obs_source_frame *frame) +{ + uint32_t size = frame->width * frame->height; + size += size/2; + + source->async_convert_width = frame->width; + source->async_convert_height = (size / frame->width + 1) & 0xFFFFFFFE; + source->async_texture_format = GS_R8; + source->async_plane_offset[0] = frame->width * frame->height; + return true; +} + static inline bool init_gpu_conversion(struct obs_source *source, struct obs_source_frame *frame) { @@ -811,8 +824,7 @@ static inline bool init_gpu_conversion(struct obs_source *source, return set_planar420_sizes(source, frame); case CONVERT_NV12: - assert(false && "NV12 not yet implemented"); - /* TODO: implement conversion */ + return set_nv12_sizes(source, frame); break; case CONVERT_NONE: @@ -897,7 +909,8 @@ static void upload_raw_frame(gs_texture_t *tex, break; case CONVERT_NV12: - assert(false && "Conversion not yet implemented"); + gs_texture_set_image(tex, frame->data[0], + frame->width, false); break; case CONVERT_NONE: @@ -922,7 +935,7 @@ static const char *select_conversion_technique(enum video_format format) return "I420_Reverse"; case VIDEO_FORMAT_NV12: - assert(false && "Conversion not yet implemented"); + return "NV12_Reverse"; break; case VIDEO_FORMAT_BGRA: