#include <mfapi.h>
#include "conversion.h"
ConversionFunction gFormatConversions[] =
{
{ MFVideoFormat_RGB32, TransformImage_RGB32 },
{ MFVideoFormat_RGB24, TransformImage_RGB24 },
{ MFVideoFormat_YUY2, TransformImage_YUY2 },
{ MFVideoFormat_NV12, TransformImage_NV12 }
};
const DWORD gConversionFormats = 4;
void TransformImage_RGB24(
BYTE* aDest,
LONG aDestStride,
const BYTE* aSrc,
LONG aSrcStride,
DWORD aWidthInPixels,
DWORD aHeightInPixels
)
{
for (DWORD y = 0; y < aHeightInPixels; y++)
{
RGBTRIPLE *srcPel = (RGBTRIPLE*)aSrc;
DWORD *destPel = (DWORD*)aDest;
for (DWORD x = 0; x < aWidthInPixels; x++)
{
destPel[x] = (
(srcPel[x].rgbtRed << 16) |
(srcPel[x].rgbtGreen << 8) |
(srcPel[x].rgbtBlue << 0) |
(0xff << 24)
);
}
aSrc += aSrcStride;
aDest += aDestStride;
}
}
void TransformImage_RGB32(
BYTE* aDest,
LONG aDestStride,
const BYTE* aSrc,
LONG aSrcStride,
DWORD aWidthInPixels,
DWORD aHeightInPixels
)
{
MFCopyImage(aDest, aDestStride, aSrc, aSrcStride, aWidthInPixels * 4, aHeightInPixels);
}
__forceinline BYTE Clip(int aClr)
{
return (BYTE)(aClr < 0 ? 0 : (aClr > 255 ? 255 : aClr));
}
__forceinline RGBQUAD ConvertYCrCbToRGB(
int aY,
int aCr,
int aCb
)
{
RGBQUAD rgbq;
int c = aY - 16;
int d = aCb - 128;
int e = aCr - 128;
rgbq.rgbRed = Clip((298 * c + 409 * e + 128) >> 8);
rgbq.rgbGreen = Clip((298 * c - 100 * d - 208 * e + 128) >> 8);
rgbq.rgbBlue = Clip((298 * c + 516 * d + 128) >> 8);
return rgbq;
}
void TransformImage_YUY2(
BYTE* aDest,
LONG aDestStride,
const BYTE* aSrc,
LONG aSrcStride,
DWORD aWidthInPixels,
DWORD aHeightInPixels
)
{
for (DWORD y = 0; y < aHeightInPixels; y++)
{
RGBQUAD *destPel = (RGBQUAD*)aDest;
WORD *srcPel = (WORD*)aSrc;
for (DWORD x = 0; x < aWidthInPixels; x += 2)
{
int y0 = (int)LOBYTE(srcPel[x]);
int u0 = (int)HIBYTE(srcPel[x]);
int y1 = (int)LOBYTE(srcPel[x + 1]);
int v0 = (int)HIBYTE(srcPel[x + 1]);
destPel[x] = ConvertYCrCbToRGB(y0, v0, u0);
destPel[x + 1] = ConvertYCrCbToRGB(y1, v0, u0);
}
aSrc += aSrcStride;
aDest += aDestStride;
}
}
void TransformImage_NV12(
BYTE* aDst,
LONG aDstStride,
const BYTE* aSrc,
LONG aSrcStride,
DWORD aWidthInPixels,
DWORD aHeightInPixels
)
{
const BYTE* bitsY = aSrc;
const BYTE* bitsCb = bitsY + (aHeightInPixels * aSrcStride);
const BYTE* bitsCr = bitsCb + 1;
for (UINT y = 0; y < aHeightInPixels; y += 2)
{
const BYTE* lineY1 = bitsY;
const BYTE* lineY2 = bitsY + aSrcStride;
const BYTE* lineCr = bitsCr;
const BYTE* lineCb = bitsCb;
LPBYTE dibLine1 = aDst;
LPBYTE dibLine2 = aDst + aDstStride;
for (UINT x = 0; x < aWidthInPixels; x += 2)
{
int y0 = (int)lineY1[0];
int y1 = (int)lineY1[1];
int y2 = (int)lineY2[0];
int y3 = (int)lineY2[1];
int cb = (int)lineCb[0];
int cr = (int)lineCr[0];
RGBQUAD r = ConvertYCrCbToRGB(y0, cr, cb);
dibLine1[0] = r.rgbBlue;
dibLine1[1] = r.rgbGreen;
dibLine1[2] = r.rgbRed;
dibLine1[3] = 0;
r = ConvertYCrCbToRGB(y1, cr, cb);
dibLine1[4] = r.rgbBlue;
dibLine1[5] = r.rgbGreen;
dibLine1[6] = r.rgbRed;
dibLine1[7] = 0;
r = ConvertYCrCbToRGB(y2, cr, cb);
dibLine2[0] = r.rgbBlue;
dibLine2[1] = r.rgbGreen;
dibLine2[2] = r.rgbRed;
dibLine2[3] = 0;
r = ConvertYCrCbToRGB(y3, cr, cb);
dibLine2[4] = r.rgbBlue;
dibLine2[5] = r.rgbGreen;
dibLine2[6] = r.rgbRed;
dibLine2[7] = 0;
lineY1 += 2;
lineY2 += 2;
lineCr += 2;
lineCb += 2;
dibLine1 += 8;
dibLine2 += 8;
}
aDst += (2 * aDstStride);
bitsY += (2 * aSrcStride);
bitsCr += aSrcStride;
bitsCb += aSrcStride;
}
}