在做视频回调解码时,需要用到数据转换,找了很多,后来公司同事写了一个,基本上可以通用,发出来给大家分享下。
/// <summary>
/// 将YV12转换成RGB32
/// </summary>
/// <param name="pYU12">yv12数据</param>
/// <param name="lPicHeight">图片高度</param>
/// <param name="lPicWidth">图片宽度</param>
/// <returns></returns>
public static byte[] GetRgb32_From_Yv12(IntPtr pYV12, Int32 lPicHeight, Int32 lPicWidth)
{
// YUV平面
byte[] pYPlaneByte = new byte[lPicHeight * lPicWidth];
byte[] pUPlaneByte = new byte[(lPicHeight / 2) * (lPicWidth / 2)];
byte[] pVPlaneByte = new byte[(lPicHeight / 2) * (lPicWidth / 2)];
// 根据解码数据首地址及分量长度,进行地址偏移,获取各YUV分量的内存地址
IntPtr pYPlaneAddr = (IntPtr)(pYV12.ToInt32() + 0);
IntPtr pUPlaneAddr = (IntPtr)(pYV12.ToInt32() + lPicHeight * lPicWidth);
IntPtr pVPlaneAddr = (IntPtr)(pYV12.ToInt32() + lPicHeight * lPicWidth + (lPicHeight / 2) * (lPicWidth / 2));
// 将YUV数据从非托管内存指针复制到托管 8 位无符号整数数组。
Marshal.Copy(pYPlaneAddr, pYPlaneByte, 0, lPicHeight * lPicWidth);
Marshal.Copy(pUPlaneAddr, pUPlaneByte, 0, (lPicHeight / 2) * (lPicWidth / 2));
Marshal.Copy(pVPlaneAddr, pVPlaneByte, 0, (lPicHeight / 2) * (lPicWidth / 2));
//YV12转换到RGB32
byte[] Rgba32 = GetRgb32_From_Yv12(pYPlaneByte, pUPlaneByte, pVPlaneByte, lPicHeight, lPicWidth);
return Rgba32;
}
/// <summary>
/// YUV12转RGB32
/// </summary>
/// <param name="pYPlaneByte"></param>
/// <param name="pUPlaneByte"></param>
/// <param name="pVPlaneByte"></param>
/// <param name="lPicHeight"></param>
/// <param name="lPicWidth"></param>
/// <returns></returns>
public static byte[] GetRgb32_From_Yv12(byte[] pYPlaneByte, byte[] pUPlaneByte, byte[] pVPlaneByte, Int32 lPicHeight, Int32 lPicWidth)
{
int picSize = lPicWidth * lPicHeight;
byte[] pRrgaByte = new byte[picSize * 4];
int A = 0;
for (int iRow = 0; iRow < lPicHeight; iRow++)
{
for (int jCol = 0; jCol < lPicWidth; jCol++)
{
int Y = pYPlaneByte[iRow * lPicWidth + jCol];
int U = pUPlaneByte[(iRow / 2) * (lPicWidth / 2) + (jCol / 2)];
int V = pVPlaneByte[(iRow / 2) * (lPicWidth / 2) + (jCol / 2)];
int R = Y + (U - 128) + (((U - 128) * 103) >> 8);
int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);
int B = Y + (V - 128) + (((V - 128) * 198) >> 8);
R = Math.Max(0, Math.Min(255, R));
G = Math.Max(0, Math.Min(255, G));
B = Math.Max(0, Math.Min(255, B));
pRrgaByte[4 * (iRow * lPicWidth + jCol) + 0] = Convert.ToByte(B);
pRrgaByte[4 * (iRow * lPicWidth + jCol) + 1] = Convert.ToByte(G);
pRrgaByte[4 * (iRow * lPicWidth + jCol) + 2] = Convert.ToByte(R);
pRrgaByte[4 * (iRow * lPicWidth + jCol) + 3] = Convert.ToByte(A);
//pRrgaByte[4 * (iRow * lPicWidth + jCol) + 0] = Convert.ToByte(R);
//pRrgaByte[4 * (iRow * lPicWidth + jCol) + 1] = Convert.ToByte(G);
//pRrgaByte[4 * (iRow * lPicWidth + jCol) + 2] = Convert.ToByte(B);
//pRrgaByte[4 * (iRow * lPicWidth + jCol) + 3] = Convert.ToByte(A);
}
}
return pRrgaByte;
}