Browse Source

libobs: Add NV12_Reverse shader

jp9000 10 years ago
parent
commit
817a724dea
2 changed files with 51 additions and 4 deletions
  1. 34 0
      libobs/data/format_conversion.effect
  2. 17 4
      libobs/obs-source.c

+ 34 - 0
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);
+	}
+}

+ 17 - 4
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: