Browse Source

Merge pull request #1906 from jpark37/bgr-three

libobs: linux-v412: obs-ffmpeg: Add packed BGR3 video support
Jim 6 years ago
parent
commit
fafda14963

+ 43 - 0
libobs/data/format_conversion.effect

@@ -378,6 +378,31 @@ float4 PSRGB_Limited(VertInOut vert_in) : TARGET
 	return rgba;
 }
 
+float4 PSBGR3_Limited(VertInOut vert_in) : TARGET
+{
+	int x = int(vert_in.uv.x * width * 3.0 + PRECISION_OFFSET);
+	int y = int(vert_in.uv.y * height      + PRECISION_OFFSET);
+
+	float b = image.Load(int3(x - 1, y, 0)).x;
+	float g = image.Load(int3(x, y, 0)).x;
+	float r = image.Load(int3(x + 1, y, 0)).x;
+	float3 rgb = float3(r, g, b);
+	rgb = saturate((rgb - (16.0 / 255.0)) * (255.0 / 219.0));
+	return float4(rgb, 1.0);
+}
+
+float4 PSBGR3_Full(VertInOut vert_in) : TARGET
+{
+	int x = int(vert_in.uv.x * width * 3.0 + PRECISION_OFFSET);
+	int y = int(vert_in.uv.y * height      + PRECISION_OFFSET);
+
+	float b = image.Load(int3(x - 1, y, 0)).x;
+	float g = image.Load(int3(x, y, 0)).x;
+	float r = image.Load(int3(x + 1, y, 0)).x;
+	float3 rgb = float3(r, g, b);
+	return float4(rgb, 1.0);
+}
+
 technique Planar420
 {
 	pass
@@ -503,3 +528,21 @@ technique RGB_Limited
 		pixel_shader  = PSRGB_Limited(vert_in);
 	}
 }
+
+technique BGR3_Limited
+{
+	pass
+	{
+		vertex_shader = VSDefault(vert_in);
+		pixel_shader  = PSBGR3_Limited(vert_in);
+	}
+}
+
+technique BGR3_Full
+{
+	pass
+	{
+		vertex_shader = VSDefault(vert_in);
+		pixel_shader  = PSBGR3_Full(vert_in);
+	}
+}

+ 8 - 0
libobs/media-io/video-frame.c

@@ -101,6 +101,13 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
 		frame->linesize[1] = width;
 		frame->linesize[2] = width;
 		break;
+
+	case VIDEO_FORMAT_BGR3:
+		size = width * height * 3;
+		ALIGN_SIZE(size, alignment);
+		frame->data[0] = bmalloc(size);
+		frame->linesize[0] = width*3;
+		break;
 	}
 }
 
@@ -129,6 +136,7 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
 	case VIDEO_FORMAT_RGBA:
 	case VIDEO_FORMAT_BGRA:
 	case VIDEO_FORMAT_BGRX:
+	case VIDEO_FORMAT_BGR3:
 		memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
 		break;
 

+ 5 - 0
libobs/media-io/video-io.h

@@ -50,6 +50,9 @@ enum video_format {
 
 	/* planar 4:4:4 */
 	VIDEO_FORMAT_I444,
+
+	/* more packed uncompressed formats */
+	VIDEO_FORMAT_BGR3,
 };
 
 enum video_colorspace {
@@ -99,6 +102,7 @@ static inline bool format_is_yuv(enum video_format format)
 	case VIDEO_FORMAT_BGRA:
 	case VIDEO_FORMAT_BGRX:
 	case VIDEO_FORMAT_Y800:
+	case VIDEO_FORMAT_BGR3:
 		return false;
 	}
 
@@ -118,6 +122,7 @@ static inline const char *get_video_format_name(enum video_format format)
 	case VIDEO_FORMAT_BGRX: return "BGRX";
 	case VIDEO_FORMAT_I444: return "I444";
 	case VIDEO_FORMAT_Y800: return "Y800";
+	case VIDEO_FORMAT_BGR3: return "BGR3";
 	case VIDEO_FORMAT_NONE:;
 	}
 

+ 1 - 0
libobs/media-io/video-scaler-ffmpeg.c

@@ -40,6 +40,7 @@ static inline enum AVPixelFormat get_ffmpeg_video_format(
 	case VIDEO_FORMAT_BGRX: return AV_PIX_FMT_BGRA;
 	case VIDEO_FORMAT_Y800: return AV_PIX_FMT_GRAY8;
 	case VIDEO_FORMAT_I444: return AV_PIX_FMT_YUV444P;
+	case VIDEO_FORMAT_BGR3: return AV_PIX_FMT_BGR24;
 	}
 
 	return AV_PIX_FMT_NONE;

+ 21 - 0
libobs/obs-source.c

@@ -1332,6 +1332,7 @@ enum convert_type {
 	CONVERT_444,
 	CONVERT_800,
 	CONVERT_RGB_LIMITED,
+	CONVERT_BGR3,
 };
 
 static inline enum convert_type get_convert_type(enum video_format format,
@@ -1359,6 +1360,9 @@ static inline enum convert_type get_convert_type(enum video_format format,
 	case VIDEO_FORMAT_BGRA:
 	case VIDEO_FORMAT_BGRX:
 		return full_range ? CONVERT_NONE : CONVERT_RGB_LIMITED;
+
+	case VIDEO_FORMAT_BGR3:
+		return CONVERT_BGR3;
 	}
 
 	return CONVERT_NONE;
@@ -1429,6 +1433,15 @@ static inline bool set_rgb_limited_sizes(struct obs_source *source,
 	return true;
 }
 
+static inline bool set_bgr3_sizes(struct obs_source *source,
+	const struct obs_source_frame *frame)
+{
+	source->async_convert_width   = frame->width * 3;
+	source->async_convert_height  = frame->height;
+	source->async_texture_format  = GS_R8;
+	return true;
+}
+
 static inline bool init_gpu_conversion(struct obs_source *source,
 		const struct obs_source_frame *frame)
 {
@@ -1452,6 +1465,9 @@ static inline bool init_gpu_conversion(struct obs_source *source,
 		case CONVERT_RGB_LIMITED:
 			return set_rgb_limited_sizes(source, frame);
 
+		case CONVERT_BGR3:
+			return set_bgr3_sizes(source, frame);
+
 		case CONVERT_NONE:
 			assert(false && "No conversion requested");
 			break;
@@ -1528,6 +1544,7 @@ static void upload_raw_frame(gs_texture_t *tex,
 		case CONVERT_422_Y:
 		case CONVERT_800:
 		case CONVERT_RGB_LIMITED:
+		case CONVERT_BGR3:
 			gs_texture_set_image(tex, frame->data[0],
 					frame->linesize[0], false);
 			break;
@@ -1570,6 +1587,9 @@ static const char *select_conversion_technique(enum video_format format,
 		case VIDEO_FORMAT_Y800:
 			return full_range ? "Y800_Full" : "Y800_Limited";
 
+		case VIDEO_FORMAT_BGR3:
+			return full_range ? "BGR3_Full" : "BGR3_Limited";
+
 		case VIDEO_FORMAT_BGRA:
 		case VIDEO_FORMAT_BGRX:
 		case VIDEO_FORMAT_RGBA:
@@ -2304,6 +2324,7 @@ static void copy_frame_data(struct obs_source_frame *dst,
 	case VIDEO_FORMAT_BGRA:
 	case VIDEO_FORMAT_BGRX:
 	case VIDEO_FORMAT_Y800:
+	case VIDEO_FORMAT_BGR3:
 		copy_frame_data_plane(dst, src, 0, dst->height);
 		break;
 	}

+ 1 - 0
plugins/linux-v4l2/v4l2-helpers.h

@@ -69,6 +69,7 @@ static inline enum video_format v4l2_to_obs_video_format(uint_fast32_t format)
 #ifdef V4L2_PIX_FMT_ABGR32
 	case V4L2_PIX_FMT_ABGR32: return VIDEO_FORMAT_BGRA;
 #endif
+	case V4L2_PIX_FMT_BGR24:  return VIDEO_FORMAT_BGR3;
 	default:                  return VIDEO_FORMAT_NONE;
 	}
 }

+ 2 - 0
plugins/obs-ffmpeg/obs-ffmpeg-formats.h

@@ -22,6 +22,7 @@ static inline enum AVPixelFormat obs_to_ffmpeg_video_format(
 	case VIDEO_FORMAT_BGRA: return AV_PIX_FMT_BGRA;
 	case VIDEO_FORMAT_BGRX: return AV_PIX_FMT_BGRA;
 	case VIDEO_FORMAT_Y800: return AV_PIX_FMT_GRAY8;
+	case VIDEO_FORMAT_BGR3: return AV_PIX_FMT_BGR24;
 	}
 
 	return AV_PIX_FMT_NONE;
@@ -39,6 +40,7 @@ static inline enum video_format ffmpeg_to_obs_video_format(
 	case AV_PIX_FMT_RGBA:    return VIDEO_FORMAT_RGBA;
 	case AV_PIX_FMT_BGRA:    return VIDEO_FORMAT_BGRA;
 	case AV_PIX_FMT_GRAY8:   return VIDEO_FORMAT_Y800;
+	case AV_PIX_FMT_BGR24:   return VIDEO_FORMAT_BGR3;
 	case AV_PIX_FMT_NONE:
 	default:                 return VIDEO_FORMAT_NONE;
 	}