rgb轉換到yuv420p nv12 yuv422p(cuda版本)

//超清公式
#define RGB2Y(R, G, B)  ( 16  + 0.183f * (R) + 0.614f * (G) + 0.062f * (B) )
#define RGB2U(R, G, B)  ( 128 - 0.101f * (R) - 0.339f * (G) + 0.439f * (B) )
#define RGB2V(R, G, B)  ( 128 + 0.439f * (R) - 0.399f * (G) - 0.040f * (B) )

#define YUV2R(Y, U, V) ( 1.164f *((Y) - 16) + 1.792f * ((V) - 128) )
#define YUV2G(Y, U, V) ( 1.164f *((Y) - 16) - 0.213f *((U) - 128) - 0.534f *((V) - 128) )
#define YUV2B(Y, U, V) ( 1.164f *((Y) - 16) + 2.114f *((U) - 128))

#define CLIPVALUE(x, minValue, maxValue) ((x) < (minValue) ? (minValue) : ((x) > (maxValue) ? (maxValue) : (x)))

__global__ static void __RgbToYuv420p(const unsigned char* dpRgbData, size_t rgbPitch, unsigned char* dpYuv420pData, size_t yuv420Pitch, int width, int height)
{
	int index = blockIdx.x * blockDim.x + threadIdx.x;
	int w = index % yuv420Pitch;
	int h = index / yuv420Pitch;

	if (w >= width || h >= height)
		return;

	unsigned char* dp_y_data = dpYuv420pData;
	unsigned char* dp_u_data = dp_y_data + height * yuv420Pitch;
	unsigned char* dp_v_data = dp_u_data + height * yuv420Pitch / 4;

	unsigned char r = dpRgbData[h * rgbPitch + w * 3 + 0];
	unsigned char g = dpRgbData[h * rgbPitch + w * 3 + 1];
	unsigned char b = dpRgbData[h * rgbPitch + w * 3 + 2];

	dp_y_data[h   * yuv420Pitch + w] = (unsigned char)(CLIPVALUE(RGB2Y(r, g, b), 0, 255));
	int num = h / 2 * width / 2 + w / 2;
	int offset = num / width * (yuv420Pitch - width);

	if (h % 2 == 0 && w % 2 == 0)
	{
		dp_u_data[num + offset] = (unsigned char)(CLIPVALUE(RGB2U(r, g, b), 0, 255));
		dp_v_data[num + offset] = (unsigned char)(CLIPVALUE(RGB2V(r, g, b), 0, 255));
	}	
}


__global__ static void __RgbToNv12(const unsigned char* dpRgbData, size_t rgbPitch, unsigned char* dpNv12Data, size_t nv12Pitch, int width, int height)
{
	int index = blockIdx.x * blockDim.x + threadIdx.x;
	int w = index % nv12Pitch;
	int h = index / nv12Pitch;

	if (w >= width || h >= height)
		return;

	unsigned char* dp_y_data = dpNv12Data;
	unsigned char* dp_u_data = dp_y_data + height * nv12Pitch;
	
	unsigned char r = dpRgbData[h * rgbPitch + w * 3 + 0];
	unsigned char g = dpRgbData[h * rgbPitch + w * 3 + 1];
	unsigned char b = dpRgbData[h * rgbPitch + w * 3 + 2];

	dp_y_data[h * nv12Pitch + w] = (unsigned char)CLIPVALUE(RGB2Y(r, g, b), 0, 255);
	int num = (h / 2 * width / 2 + w / 2);
	int offset = (num * 2 + 1) / width * (nv12Pitch - width);

	if (h % 2 == 0 && w % 2 == 0)
	{
		dp_u_data[num * 2 + 0 + offset] = (unsigned char)(CLIPVALUE(RGB2U(r, g, b), 0, 255));
		dp_u_data[num * 2 + 1 + offset] = (unsigned char)(CLIPVALUE(RGB2V(r, g, b), 0, 255));
	}
}

__global__ static void __RgbToYuv422p(const unsigned char* dpRgbData, size_t rgbPitch, unsigned char* dpYuv422pData, size_t yuv422pPitch, int width, int height)
{
	int index = blockIdx.x * blockDim.x + threadIdx.x;
	int w = index % yuv422pPitch;
	int h = index / yuv422pPitch;

	if (w >= width || h >= height)
		return;

	unsigned char* dp_y_data = dpYuv422pData;
	unsigned char* dp_u_data = dp_y_data + height * yuv422pPitch;
	unsigned char* dp_v_data = dp_u_data + height / 2 * yuv422pPitch;

	unsigned char r = dpRgbData[h * rgbPitch + w * 3 + 0];
	unsigned char g = dpRgbData[h * rgbPitch + w * 3 + 1];
	unsigned char b = dpRgbData[h * rgbPitch + w * 3 + 2];

	dp_y_data[h * yuv422pPitch + w] = (unsigned char)CLIPVALUE(RGB2Y(r, g, b), 0, 255);
	int num = h * width / 2 + w / 2;
	int offset = num / width * (yuv422pPitch - width);

	if (w % 2 == 0)
	{
		dp_u_data[num + offset] = (unsigned char)(CLIPVALUE(RGB2U(r, g, b), 0, 255));
		dp_v_data[num + offset] = (unsigned char)(CLIPVALUE(RGB2V(r, g, b), 0, 255));
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章