VFW采集免驱动USB摄相头的视频,
biCompression = 844715353, 在网上看资料介绍是YUY2格式,也就是YUV422用下面的代码转换后,发送出去;
传入的参数是VFW采集的原始视频流。接收端接受到,转成RGB24进行播放,但是视频很模糊。
不清楚什么原因int YUV422To420(unsigned char *pYUV, unsigned int *yuv, int lWidth, int lHeight)
{
int i,j;
unsigned int *pY = yuv;
unsigned int *pU = yuv + lWidth*lHeight;
unsigned int *pV = pU + (lWidth*lHeight)/4;unsigned char *pYUVTemp = pYUV;
unsigned char *pYUVTempNext = pYUV+lWidth*2;
for(i=0; i<lHeight; i+=2)
{
for(j=0; j<lWidth; j+=2)
{
pY[j] = *pYUVTemp++;
pY[j+lWidth] = *pYUVTempNext++;
pU[j/2] =(*(pYUVTemp) + *(pYUVTempNext))/2;
pYUVTemp++;
pYUVTempNext++;
pY[j+1] = *pYUVTemp++;
pY[j+1+lWidth] = *pYUVTempNext++;
pV[j/2] =(*(pYUVTemp) + *(pYUVTempNext))/2;
pYUVTemp++;
pYUVTempNext++;
}
pYUVTemp+=lWidth*2;
pYUVTempNext+=lWidth*2;
pY+=lWidth*2;
pU+=lWidth/2;
pV+=lWidth/2;
}
return 1;
}
biCompression = 844715353, 在网上看资料介绍是YUY2格式,也就是YUV422用下面的代码转换后,发送出去;
传入的参数是VFW采集的原始视频流。接收端接受到,转成RGB24进行播放,但是视频很模糊。
不清楚什么原因int YUV422To420(unsigned char *pYUV, unsigned int *yuv, int lWidth, int lHeight)
{
int i,j;
unsigned int *pY = yuv;
unsigned int *pU = yuv + lWidth*lHeight;
unsigned int *pV = pU + (lWidth*lHeight)/4;unsigned char *pYUVTemp = pYUV;
unsigned char *pYUVTempNext = pYUV+lWidth*2;
for(i=0; i<lHeight; i+=2)
{
for(j=0; j<lWidth; j+=2)
{
pY[j] = *pYUVTemp++;
pY[j+lWidth] = *pYUVTempNext++;
pU[j/2] =(*(pYUVTemp) + *(pYUVTempNext))/2;
pYUVTemp++;
pYUVTempNext++;
pY[j+1] = *pYUVTemp++;
pY[j+1+lWidth] = *pYUVTempNext++;
pV[j/2] =(*(pYUVTemp) + *(pYUVTempNext))/2;
pYUVTemp++;
pYUVTempNext++;
}
pYUVTemp+=lWidth*2;
pYUVTempNext+=lWidth*2;
pY+=lWidth*2;
pU+=lWidth/2;
pV+=lWidth/2;
}
return 1;
}
biBitCount = 16
看网上介绍说是 YUY2格式, 我也不是很确定.
unsigned char* pY, unsigned char* pU, unsigned char* pV,
int lWidth, int lHeight)之前看别的程序, 有的多传入三个参数
unsigned char* pY, unsigned char* pU, unsigned char* pV,
不知道这个是否有影响...
算法实现上,Y不变化,纯属拷贝
至于UV,算法一样,即YUYV的奇场和偶场分别进行插值按序产生YUV420中UV的一行,而不是你代码中的奇行和偶行进行平均插值
另外,看你UV插值算法中使用的是平均插值,也可以修改,奇场使用3:1插值,偶场使用1:3插值,即对称计算
int YUV422To420(unsigned char *pYUV, unsigned int *yuv, int lWidth, int lHeight)
{
int i,j;
unsigned int *pY = yuv;
unsigned int *pU = yuv + lWidth*lHeight;
unsigned int *pV = pU + (lWidth*lHeight)/4;unsigned char *pYUVTemp = pYUV;
unsigned char *pYUVTempNext = pYUV+lWidth*2;
unsigned char *pYUV2 = pYUVTempNext + lWidth*2;
unsigned char *pYUV3 = pYUVTempNext + lWidth*4;
for(i=0; i<lHeight; i+=4)
{
for(j=0; j<lWidth; j+=4)
{
// Y0
pY[j] = *pYUVTemp++;
pY[j+lWidth] = *pYUVTempNext++;
pY[j+lWidth*2] = *pYUV2++;
pY[j+lWidth*3] = *pYUV3++;
// U
pU[j/2] = (3*pYUVTemp[j] + pYUV2[j])/4;
pU[j/2+lWidth/2] = (pYUVTempNext[j] + 3*pYUV3[j])/4;
// Y1
pY[j+1] = *pYUVTemp++;
pY[j+lWidth+1] = *pYUVTempNext++;
pY[j+lWidth*2+1] = *pYUV2++;
pY[j+lWidth*3+1] = *pYUV3++;
// V
pV[j/2] = (3*pYUVTemp[j] + pYUV2[j])/4;
pV[j/2+lWidth/2] = (pYUVTempNext[j] + 3*pYUV3[j])/4; }
pYUVTemp+=lWidth*2*4;
pYUVTempNext+=lWidth*2*4;
pYUV2+=lWidth*2*4;
pYUV3+=lWidth*2*4;
pY+=lWidth*4;
pU+=lWidth;
pV+=lWidth;
}
return 1;
}
{
for(j=0; j<lWidth; j+=4)
{
// Y0
pY[j] = *pYUVTemp++;
pY[j+lWidth] = *pYUVTempNext++;
pY[j+lWidth*2] = *pYUV2++;
pY[j+lWidth*3] = *pYUV3++; //执行到该行代码,出现异常//获取摄相头原始视频的相关参数
capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));m_bmpinfo.bmiHeader.biSize =40
m_bmpinfo.bmiHeader.biWidth =176
m_bmpinfo.bmiHeader.biHeight =144
m_bmpinfo.bmiHeader.biPlanes =1
m_bmpinfo.bmiHeader.biBitCount =16
m_bmpinfo.bmiHeader.biCompression =844715353
m_bmpinfo.bmiHeader.biSizeImage =50688
书籍可以参考“视频技术手册”,上面有YUV422到YUV420采样转换的讲解int YUV422To420(unsigned char *pYUV, unsigned int *yuv, int lWidth, int lHeight)
{
int i,j;
unsigned int *pY = yuv;
unsigned int *pU = yuv + lWidth*lHeight;
unsigned int *pV = pU + (lWidth*lHeight)/4;unsigned char *pYUVTemp = pYUV;
unsigned char *pYUVTempNext = pYUV+lWidth*2;
unsigned char *pYUV2 = pYUVTempNext + lWidth*2;
unsigned char *pYUV3 = pYUVTempNext + lWidth*4;
for(i=0; i<lHeight; i+=4)
{
for(j=0; j<lWidth; j+=4)
{
// Y0
pY[j] = pYUVTemp[j];
pY[j+lWidth] = pYUVTempNext[j];
pY[j+lWidth*2] = pYUV2[j];
pY[j+lWidth*3] = pYUV3[j];
// U
pU[j/2] = (3*pYUVTemp[j+1] + pYUV2[j+1])/4;
pU[j/2+lWidth/2] = (pYUVTempNext[j+1] + 3*pYUV3[j+1])/4;
// Y1
pY[j+1] = pYUVTemp[j+2];
pY[j+lWidth+1] = pYUVTempNext[j+2];
pY[j+lWidth*2+1] = pYUV2[j+2];
pY[j+lWidth*3+1] = pYUV3[j+2];
// V
pV[j/2] = (3*pYUVTemp[j+3] + pYUV2[j+3])/4;
pV[j/2+lWidth/2] = (pYUVTempNext[j+3] + 3*pYUV3[j+3])/4; }
// 分别加四行
pYUVTemp+=lWidth*2*4;
pYUVTempNext+=lWidth*2*4;
pYUV2+=lWidth*2*4;
pYUV3+=lWidth*2*4;
// Y加上四行
pY+=lWidth*4;
// UV加两行
pU+=lWidth;
pV+=lWidth;
}
return 1;
}
RGB24 的 biBitCount = 24 ????去我的资源看看吧,也许有你需要的东西。
好象有驱动的,一般都是24位, RGB24
免驱动的一般都是16位, 大概是 YUY2
YUYV/UYVY,每个像素16bit,因为第二个UV丢弃
RGBA,每个像素32bit
RGB/BGR,每个像素24Bit
YUV422/YUV420/YUV411,分片数据,Y一片,U一片,V一片
可查询微软MSDN,或者参考《视频技术手册》
YUY2是免驱动USB摄相头,采集的原始视频,
具体是分片,还是打包方式,还不是太清楚.biCompression = 844715353
biBitCount = 16
看网上介绍说是 YUY2格式, 我也不是很确定.通过VFW的API来设置biBitCount = 24, 但是设置不成功.
排列即为Y0 U0 Y1 V0 Y2 U2 Y3 V2 Y4 U4 Y5 V4...
注意到,Y是没有丢弃的,但是U和V丢弃了偶数列像素(索引从0开始,即丢弃了U1,V1,U3,V3...)
用C++封装DLL来采集视频,通过回调函数传给C#,
然后让C#来播放;RGB格式的播放没有问题,但是YUY2格式的播放的时候,屏幕总是闪烁,
一会清晰,一会绿屏,感觉数据有问题。不知道是C#不能直接播放YUY2数据,还是因为通过回调函数回发数据的速度太快了。在C#版块发的一个帖子C# 是否可以播放YUY2格式的视频?
http://topic.csdn.net/u/20110706/17/6b6fe826-4d28-4d6c-bb0e-0abc8db15c08.html