From 9a680c588248abec30f7a4afdcf7a18c58766ade Mon Sep 17 00:00:00 2001
From: Sayit BELET <admintv@encoder>
Date: Mon, 3 Oct 2016 12:09:58 +0300
Subject: [PATCH] For 10bit SDI Sources to 10bit NVENC Encode 10bit YUV422P to
 P010 yuv422p10ToP010Wrapper

For 8bit SDI Sources to 10bit NVENC Encode
8bit YUV422 to P010
uyvy422ToP010Wrapper

For 10bit SDI Sources to 8bit NVENC Encode
10bit YUV422P to 8bit YUV420P
yuv422p10ToYuv420pWrapper
---
 libswscale/swscale_unscaled.c | 140 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index e46763c..8cffa42 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -237,6 +237,135 @@ static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[],
     return srcSliceH;
 }
 
+static int yuv422p10ToP010Wrapper(SwsContext *c,
+										const uint8_t *src8[],
+										int *srcStride, int srcSliceY,
+										int srcSliceH, uint8_t *dstParam8[],
+										int *dstStride)
+{
+	const uint16_t **src = (const uint16_t**)src8;
+	uint16_t *dstY  = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY);
+	uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2);
+	int x, y;
+
+	av_assert0(!(srcStride[0] % 2 || srcStride[1] % 2 || srcStride[2] % 2 ||
+	             dstStride[0] % 2 || dstStride[1] % 2));
+
+	for (y = 0; y < srcSliceH; y++) {
+		uint16_t *tdstY = dstY;
+		const uint16_t *tsrc0 = src[0];
+		for (x = c->srcW; x > 0; --x)
+			*tdstY++ = *tsrc0++ << 6;
+
+		src[0] += srcStride[0] / 2;
+		dstY += dstStride[0] / 2;
+
+		if (!(y & 1)) {
+			uint16_t *tdstUV = dstUV;
+			const uint16_t *tsrc1 = src[1];
+			const uint16_t *tsrc2 = src[2];
+			for (x = c->srcW / 2; x > 0; x--) {
+				*tdstUV++ = *tsrc1++ << 6;
+				*tdstUV++ = *tsrc2++ << 6;
+			}
+
+			src[1] += srcStride[1]; // U
+			src[2] += srcStride[2]; // V
+			dstUV  += dstStride[1] / 2;
+		}
+	}
+
+	return srcSliceH;
+}
+
+static int yuv422p10ToYuv420pWrapper(SwsContext *c,
+										const uint8_t *src8[],
+										int *srcStride, int srcSliceY,
+										int srcSliceH, uint8_t *dstParam8[],
+										int *dstStride)
+{
+	const uint16_t **src = (const uint16_t**)src8;
+	uint8_t *ydst = dstParam8[0] + dstStride[0] * srcSliceY;
+	uint8_t *udst = dstParam8[1] + dstStride[1] * srcSliceY / 2;
+	uint8_t *vdst = dstParam8[2] + dstStride[2] * srcSliceY / 2;
+	int x, y;
+
+	av_assert0(!(srcStride[0] % 2 || srcStride[1] % 2 || srcStride[2] % 2 ||
+	             dstStride[0] % 2 || dstStride[1] % 2));
+
+	for (y = 0; y < srcSliceH; y++)	{
+		const uint16_t *tsrc0 = src[0];
+		uint8_t *tdst0 = ydst;
+
+		for (x = 0; x < c->srcW; ++x)
+			*tdst0++ = *tsrc0++ >> 2;
+
+		src[0] += srcStride[0] / 2;
+		ydst   += dstStride[0];
+
+		if (!(y & 1)) {
+			uint8_t *tdst1 = udst;
+			uint8_t *tdst2 = vdst;
+			const uint16_t *tsrc1 = src[1];
+			const uint16_t *tsrc2 = src[2];
+			for (x = c->srcW / 2; x > 0; x--) {
+				*tdst1++ = *tsrc1++ >> 2; // U
+				*tdst2++ = *tsrc2++ >> 2; // V
+			}
+
+			src[1] += srcStride[1]; // U
+			src[2] += srcStride[2]; // V
+			udst   += dstStride[1]; // U
+			vdst   += dstStride[2]; // V
+		}
+	}
+
+	return srcSliceH;
+}
+
+static int uyvy422ToP010Wrapper(SwsContext *c, const uint8_t *src[],
+                               int srcStride[], int srcSliceY, int srcSliceH,
+                               uint8_t *dstParam[], int dstStride[])
+{
+	uint16_t *dstY  = (uint16_t*)(dstParam[0] + dstStride[0] * srcSliceY);
+	uint16_t *dstUV = (uint16_t*)(dstParam[1] + dstStride[1] * srcSliceY / 2);
+	int x, y;
+
+	for (y = 0; y < srcSliceH; y++)	{
+		uint16_t *tdstY  = dstY;	// dest Y
+		uint16_t *tdstUV = dstUV;	// dest U-V (LSW) contains the U and (MSW) contains the V value
+		const uint8_t *tsrc0 = src[0] + 1;	// source Y
+		const uint8_t *tsrc1 = src[0] + 0;	// source U
+		const uint8_t *tsrc2 = src[0] + 2;	// source V
+
+		for (x = c->srcW; x > 0; x--) {
+			*tdstY++ = *tsrc0 << 8;
+			tsrc0 += 2;
+		}
+
+		if (!(y & 1)) {
+			tdstUV = dstUV;
+			tsrc1 = src[0] + 0; // source U
+			tsrc2 = src[0] + 2; // source V
+
+			for (x=0; x < c->srcW / 2; ++x) {
+				*tdstUV++ = *tsrc1 << 8; // U 0
+				*tdstUV++ = *tsrc2 << 8; // V 0
+
+				tsrc1 += 4;
+				tsrc2 += 4;
+			}
+
+			dstUV += dstStride[1] / 2;
+		}
+
+		src[0] += srcStride[0];
+		dstY   += dstStride[0] / 2;
+	}
+
+    return srcSliceH;
+}
+
 #if AV_HAVE_BIGENDIAN
 #define output_pixel(p, v) do { \
         uint16_t *pp = (p); \
@@ -1705,6 +1834,16 @@ void ff_get_unscaled_swscale(SwsContext *c)
         dstFormat == AV_PIX_FMT_P010) {
         c->swscale = planarToP010Wrapper;
     }
+	/* yuv422p10_to_p010 */
+	if ((srcFormat == AV_PIX_FMT_YUV422P10 || srcFormat == AV_PIX_FMT_YUVA422P10) && dstFormat == AV_PIX_FMT_P010)
+		c->swscale = yuv422p10ToP010Wrapper;
+	/* yuv422p10_to_yuv420p */
+	if ((srcFormat == AV_PIX_FMT_YUV422P10 || srcFormat == AV_PIX_FMT_YUVA422P10) &&
+		(dstFormat == AV_PIX_FMT_YUV420P) || srcFormat == AV_PIX_FMT_YUVA420P)
+		c->swscale = yuv422p10ToYuv420pWrapper;
+	/* uyvy422_to_p010 */
+	if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_P010)
+		c->swscale = uyvy422ToP010Wrapper;
     /* yuv420p_to_p010le */
     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
         dstFormat == AV_PIX_FMT_P010LE) {
@@ -1917,3 +2056,4 @@ void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
         dst += 3;
     }
 }
+
-- 
1.9.1

