Browse Source

libobs: Add PQ/HLG support for I210/I412 formats

Seen when playing back ProRes files.
jpark37 2 years ago
parent
commit
0efaf88caf
2 changed files with 106 additions and 2 deletions
  1. 90 0
      libobs/data/format_conversion.effect
  2. 16 2
      libobs/obs-source.c

+ 90 - 0
libobs/data/format_conversion.effect

@@ -573,6 +573,32 @@ float4 PSPlanar422_10LE_Reverse(VertTexPos frag_in) : TARGET
 	return float4(rgb, 1.);
 }
 
+float4 PSPlanar422_10LE_PQ_Reverse(VertTexPos frag_in) : TARGET
+{
+	float y = image.Load(int3(frag_in.pos.xy, 0)).x;
+	float cb = image1.Sample(def_sampler, frag_in.uv).x;
+	float cr = image2.Sample(def_sampler, frag_in.uv).x;
+	float3 yuv = float3(y, cb, cr);
+	yuv *= 65535. / 1023.;
+	float3 pq = YUV_to_RGB(yuv);
+	float3 hdr2020 = st2084_to_linear_eetf(pq, hdr_lw, hdr_lmax) * maximum_over_sdr_white_nits;
+	float3 rgb = rec2020_to_rec709(hdr2020);
+	return float4(rgb, 1.);
+}
+
+float4 PSPlanar422_10LE_HLG_Reverse(VertTexPos frag_in) : TARGET
+{
+	float y = image.Load(int3(frag_in.pos.xy, 0)).x;
+	float cb = image1.Sample(def_sampler, frag_in.uv).x;
+	float cr = image2.Sample(def_sampler, frag_in.uv).x;
+	float3 yuv = float3(y, cb, cr);
+	yuv *= 65535. / 1023.;
+	float3 hlg = YUV_to_RGB(yuv);
+	float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
+	float3 rgb = rec2020_to_rec709(hdr2020);
+	return float4(rgb, 1.);
+}
+
 float4 PSPlanar422A_Reverse(VertTexPos frag_in) : TARGET
 {
 	int3 xy0_luma = int3(frag_in.pos.xy, 0);
@@ -609,6 +635,34 @@ float4 PSPlanar444_12LE_Reverse(FragPos frag_in) : TARGET
 	return float4(rgb, 1.);
 }
 
+float4 PSPlanar444_12LE_PQ_Reverse(FragPos frag_in) : TARGET
+{
+	int3 xy0 = int3(frag_in.pos.xy, 0);
+	float y = image.Load(xy0).x;
+	float cb = image1.Load(xy0).x;
+	float cr = image2.Load(xy0).x;
+	float3 yuv = float3(y, cb, cr);
+	yuv *= 65535. / 4095;
+	float3 pq = YUV_to_RGB(yuv);
+	float3 hdr2020 = st2084_to_linear_eetf(pq, hdr_lw, hdr_lmax) * maximum_over_sdr_white_nits;
+	float3 rgb = rec2020_to_rec709(hdr2020);
+	return float4(rgb, 1.);
+}
+
+float4 PSPlanar444_12LE_HLG_Reverse(FragPos frag_in) : TARGET
+{
+	int3 xy0 = int3(frag_in.pos.xy, 0);
+	float y = image.Load(xy0).x;
+	float cb = image1.Load(xy0).x;
+	float cr = image2.Load(xy0).x;
+	float3 yuv = float3(y, cb, cr);
+	yuv *= 65535. / 4095;
+	float3 hlg = YUV_to_RGB(yuv);
+	float3 hdr2020 = hlg_to_linear(hlg, hlg_exponent) * maximum_over_sdr_white_nits;
+	float3 rgb = rec2020_to_rec709(hdr2020);
+	return float4(rgb, 1.);
+}
+
 float4 PSPlanar444A_Reverse(FragPos frag_in) : TARGET
 {
 	int3 xy0 = int3(frag_in.pos.xy, 0);
@@ -1089,6 +1143,24 @@ technique I210_Reverse
 	}
 }
 
+technique I210_PQ_Reverse
+{
+	pass
+	{
+		vertex_shader = VS422Left_Reverse(id);
+		pixel_shader  = PSPlanar422_10LE_PQ_Reverse(frag_in);
+	}
+}
+
+technique I210_HLG_Reverse
+{
+	pass
+	{
+		vertex_shader = VS422Left_Reverse(id);
+		pixel_shader  = PSPlanar422_10LE_HLG_Reverse(frag_in);
+	}
+}
+
 technique I42A_Reverse
 {
 	pass
@@ -1116,6 +1188,24 @@ technique I412_Reverse
 	}
 }
 
+technique I412_PQ_Reverse
+{
+	pass
+	{
+		vertex_shader = VSPos(id);
+		pixel_shader  = PSPlanar444_12LE_PQ_Reverse(frag_in);
+	}
+}
+
+technique I412_HLG_Reverse
+{
+	pass
+	{
+		vertex_shader = VSPos(id);
+		pixel_shader  = PSPlanar444_12LE_HLG_Reverse(frag_in);
+	}
+}
+
 technique YUVA_Reverse
 {
 	pass

+ 16 - 2
libobs/obs-source.c

@@ -2134,7 +2134,14 @@ static const char *select_conversion_technique(enum video_format format,
 		return "I444_Reverse";
 
 	case VIDEO_FORMAT_I412:
-		return "I412_Reverse";
+		switch (trc) {
+		case VIDEO_TRC_PQ:
+			return "I412_PQ_Reverse";
+		case VIDEO_TRC_HLG:
+			return "I412_HLG_Reverse";
+		default:
+			return "I412_Reverse";
+		}
 
 	case VIDEO_FORMAT_Y800:
 		return full_range ? "Y800_Full" : "Y800_Limited";
@@ -2146,7 +2153,14 @@ static const char *select_conversion_technique(enum video_format format,
 		return "I422_Reverse";
 
 	case VIDEO_FORMAT_I210:
-		return "I210_Reverse";
+		switch (trc) {
+		case VIDEO_TRC_PQ:
+			return "I210_PQ_Reverse";
+		case VIDEO_TRC_HLG:
+			return "I210_HLG_Reverse";
+		default:
+			return "I210_Reverse";
+		}
 
 	case VIDEO_FORMAT_I40A:
 		return "I40A_Reverse";