瀏覽代碼

libobs: obs-ffmpeg: win-dshow: Planar 4:2:2 video

This format has been seen when using FFmpeg MJPEG decompression.
James Park 6 年之前
父節點
當前提交
37f663a789

+ 28 - 0
libobs/data/format_conversion.effect

@@ -363,6 +363,25 @@ float4 PSPlanar420_Reverse(FragTex frag_in) : TARGET
 	return saturate(mul(float4(yuv, 1.0), color_matrix));
 }
 
+float4 PSPlanar422_Reverse(FragTex frag_in) : TARGET
+{
+	int x = int(frag_in.uv.x * width  + PRECISION_OFFSET);
+	int y = int(frag_in.uv.y * height + PRECISION_OFFSET);
+
+	int lum_offset = y * int_width + x;
+	int chroma_offset = y * (int_width / 2) + x / 2;
+	int chroma1    = int_u_plane_offset + chroma_offset;
+	int chroma2    = int_v_plane_offset + chroma_offset;
+
+	float3 yuv = float3(
+		GetIntOffsetColor(lum_offset),
+		GetIntOffsetColor(chroma1),
+		GetIntOffsetColor(chroma2)
+	);
+	yuv = clamp(yuv, color_range_min, color_range_max);
+	return saturate(mul(float4(yuv, 1.0), color_matrix));
+}
+
 float4 PSPlanar444_Reverse(FragTex frag_in) : TARGET
 {
 	int x = int(frag_in.uv.x * width  + PRECISION_OFFSET);
@@ -535,6 +554,15 @@ technique I420_Reverse
 	}
 }
 
+technique I422_Reverse
+{
+	pass
+	{
+		vertex_shader = VSPosTex(id);
+		pixel_shader  = PSPlanar422_Reverse(frag_in);
+	}
+}
+
 technique I444_Reverse
 {
 	pass

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

@@ -108,6 +108,23 @@ void video_frame_init(struct video_frame *frame, enum video_format format,
 		frame->data[0] = bmalloc(size);
 		frame->linesize[0] = width * 3;
 		break;
+
+	case VIDEO_FORMAT_I422:
+		size = width * height;
+		ALIGN_SIZE(size, alignment);
+		offsets[0] = size;
+		size += (width / 2) * height;
+		ALIGN_SIZE(size, alignment);
+		offsets[1] = size;
+		size += (width / 2) * height;
+		ALIGN_SIZE(size, alignment);
+		frame->data[0] = bmalloc(size);
+		frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
+		frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
+		frame->linesize[0] = width;
+		frame->linesize[1] = width / 2;
+		frame->linesize[2] = width / 2;
+		break;
 	}
 }
 
@@ -141,6 +158,7 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
 		break;
 
 	case VIDEO_FORMAT_I444:
+	case VIDEO_FORMAT_I422:
 		memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
 		memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
 		memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);

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

@@ -53,6 +53,9 @@ enum video_format {
 
 	/* more packed uncompressed formats */
 	VIDEO_FORMAT_BGR3,
+
+	/* planar 4:2:2 */
+	VIDEO_FORMAT_I422,
 };
 
 enum video_colorspace {

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

@@ -53,6 +53,8 @@ get_ffmpeg_video_format(enum video_format format)
 		return AV_PIX_FMT_YUV444P;
 	case VIDEO_FORMAT_BGR3:
 		return AV_PIX_FMT_BGR24;
+	case VIDEO_FORMAT_I422:
+		return AV_PIX_FMT_YUV422P;
 	}
 
 	return AV_PIX_FMT_NONE;

+ 25 - 0
libobs/obs-source.c

@@ -1334,6 +1334,7 @@ enum convert_type {
 	CONVERT_NONE,
 	CONVERT_NV12,
 	CONVERT_420,
+	CONVERT_422,
 	CONVERT_422_U,
 	CONVERT_422_Y,
 	CONVERT_444,
@@ -1352,6 +1353,8 @@ static inline enum convert_type get_convert_type(enum video_format format,
 		return CONVERT_NV12;
 	case VIDEO_FORMAT_I444:
 		return CONVERT_444;
+	case VIDEO_FORMAT_I422:
+		return CONVERT_422;
 
 	case VIDEO_FORMAT_YVYU:
 	case VIDEO_FORMAT_YUY2:
@@ -1409,6 +1412,20 @@ static inline bool set_planar420_sizes(struct obs_source *source,
 	return true;
 }
 
+static inline bool set_planar422_sizes(struct obs_source *source,
+				       const struct obs_source_frame *frame)
+{
+	uint32_t size = frame->width * frame->height;
+	size *= 2;
+
+	source->async_convert_width = frame->width;
+	source->async_convert_height = size / frame->width;
+	source->async_texture_format = GS_R8;
+	source->async_plane_offset[0] = (int)(frame->data[1] - frame->data[0]);
+	source->async_plane_offset[1] = (int)(frame->data[2] - frame->data[0]);
+	return true;
+}
+
 static inline bool set_nv12_sizes(struct obs_source *source,
 				  const struct obs_source_frame *frame)
 {
@@ -1460,6 +1477,9 @@ static inline bool init_gpu_conversion(struct obs_source *source,
 	case CONVERT_420:
 		return set_planar420_sizes(source, frame);
 
+	case CONVERT_422:
+		return set_planar422_sizes(source, frame);
+
 	case CONVERT_NV12:
 		return set_nv12_sizes(source, frame);
 
@@ -1557,6 +1577,7 @@ static void upload_raw_frame(gs_texture_t *tex,
 		break;
 
 	case CONVERT_420:
+	case CONVERT_422:
 	case CONVERT_NV12:
 	case CONVERT_444:
 		gs_texture_set_image(tex, frame->data[0], frame->width, false);
@@ -1596,6 +1617,9 @@ static const char *select_conversion_technique(enum video_format format,
 	case VIDEO_FORMAT_BGR3:
 		return full_range ? "BGR3_Full" : "BGR3_Limited";
 
+	case VIDEO_FORMAT_I422:
+		return "I422_Reverse";
+
 	case VIDEO_FORMAT_BGRA:
 	case VIDEO_FORMAT_BGRX:
 	case VIDEO_FORMAT_RGBA:
@@ -2316,6 +2340,7 @@ static void copy_frame_data(struct obs_source_frame *dst,
 		break;
 
 	case VIDEO_FORMAT_I444:
+	case VIDEO_FORMAT_I422:
 		copy_frame_data_plane(dst, src, 0, dst->height);
 		copy_frame_data_plane(dst, src, 1, dst->height);
 		copy_frame_data_plane(dst, src, 2, dst->height);

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

@@ -35,6 +35,8 @@ obs_to_ffmpeg_video_format(enum video_format format)
 		return AV_PIX_FMT_GRAY8;
 	case VIDEO_FORMAT_BGR3:
 		return AV_PIX_FMT_BGR24;
+	case VIDEO_FORMAT_I422:
+		return AV_PIX_FMT_YUV422P;
 	}
 
 	return AV_PIX_FMT_NONE;
@@ -62,6 +64,8 @@ ffmpeg_to_obs_video_format(enum AVPixelFormat format)
 		return VIDEO_FORMAT_Y800;
 	case AV_PIX_FMT_BGR24:
 		return VIDEO_FORMAT_BGR3;
+	case AV_PIX_FMT_YUV422P:
+		return VIDEO_FORMAT_I422;
 	case AV_PIX_FMT_NONE:
 	default:
 		return VIDEO_FORMAT_NONE;

+ 3 - 0
plugins/win-dshow/ffmpeg-decode.c

@@ -74,6 +74,9 @@ static inline enum video_format convert_pixel_format(int f)
 		return VIDEO_FORMAT_YUY2;
 	case AV_PIX_FMT_UYVY422:
 		return VIDEO_FORMAT_UYVY;
+	case AV_PIX_FMT_YUV422P:
+	case AV_PIX_FMT_YUVJ422P:
+		return VIDEO_FORMAT_I422;
 	case AV_PIX_FMT_RGBA:
 		return VIDEO_FORMAT_RGBA;
 	case AV_PIX_FMT_BGRA: