现在的位置: 首页 > 综合 > 正文

windows mobile视频通话开发记录

2013年05月29日 ⁄ 综合 ⁄ 共 3046字 ⁄ 字号 评论关闭
系统架构(暂时不处理音频通话部分):

获取摄像头数据-->编码-->传输->解码->播放

1.获取摄像头数据
通过DShow已经可以得到16RGB或者24RGB(略)

2.转化数据到YUV420
// Conversion from RGB to YUV420
int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
int RGB2YUV_VG[256], RGB2YUV_VB[256];

void InitLookupTable()
{
int i;

 for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i<<8);
}

//
//  Convert from  RGB24 to YUV420
//
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned int *yuv)
{

unsigned int *u,*v,*y,*uu,*vv;
unsigned int *pu1,*pu2,*pu3,*pu4;
unsigned int *pv1,*pv2,*pv3,*pv4;
unsigned char *r,*g,*b;
int i,j;

uu=new unsigned int[w*h];
vv=new unsigned int[w*h];

if(uu==NULL || vv==NULL)
return 0;

y=yuv;
u=uu;
v=vv;

// Get r,g,b pointers from bmp image data....
r=bmp;
g=bmp+1;
b=bmp+2;

//Get YUV values for rgb values...

 for(i=0;i<h;i++)
{

for(j=0;j<w;j++)
{
*y++=( RGB2YUV_YR[*r]  +RGB2YUV_YG[*g]+RGB2YUV_YB[*b]+1048576)>>16;
*u++=(-RGB2YUV_UR[*r]  -RGB2YUV_UG[*g]+RGB2YUV_UBVR[*b]+8388608)>>16;
*v++=( RGB2YUV_UBVR[*r]-RGB2YUV_VG[*g]-RGB2YUV_VB[*b]+8388608)>>16;

  r+=3;
g+=3;
b+=3;
}

}

这是网上流传的经典的转换代码,按理应该没错,但是起初用的时候根本无法正确转换,后来将unsigned int全部改为unsigned char,可以转换,但是图像是倒立的,并且颜色偏绿,之所以说经典是效率高。

下面看另一种转换:

void ReadBmp(unsigned char *RGB,FILE *fp)//便于调试用本地图片载入数据
{
int i,j;
unsigned char temp;

fseek(fp,54, SEEK_SET);

fread(RGB+WIDTH*HEIGHT*3, 1, WIDTH*HEIGHT*3, fp);//读取
for(i=HEIGHT-1,j=0; i>=0; i--,j++)//调整顺序
{
memcpy(RGB+j*WIDTH*3,RGB+WIDTH*HEIGHT*3+i*WIDTH*3,WIDTH*3);
}
//这里做了顺序调整,所以出来的图片是正常的方向,可见第一种方法没有进行数据顺序转换
//顺序调整
for(i=0; (unsigned int)i < WIDTH*HEIGHT*3; i+=3)
{
temp = RGB[i];
RGB[i] = RGB[i+2];
RGB[i+2] = temp;
}
}

void Convert(unsigned char *RGB, unsigned char *YUV)
{
//变量声明
unsigned int i,x,y,j;
unsigned char *Y = NULL;
unsigned char *U = NULL;
unsigned char *V = NULL;

Y = YUV;
U = YUV + WIDTH*HEIGHT;
V = U + ((WIDTH*HEIGHT)>>2);

for(y=0; y < HEIGHT; y++)
for(x=0; x < WIDTH; x++)
{
j = y*WIDTH + x;
i = j*3;
Y[j] = (unsigned char)(DY(RGB[i], RGB[i+1], RGB[i+2]));

if(x%2 == 1 && y%2 == 1)
{
j = (WIDTH>>1) * (y>>1) + (x>>1);
//上面i仍有效
U[j] = (unsigned char)
((DU(RGB[i  ], RGB[i+1], RGB[i+2]) +
DU(RGB[i-3], RGB[i-2], RGB[i-1]) +
DU(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +
DU(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);

V[j] = (unsigned char)
((DV(RGB[i  ], RGB[i+1], RGB[i+2]) +
DV(RGB[i-3], RGB[i-2], RGB[i-1]) +
DV(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +
DV(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);
}

}
}

第二种方法OK,转换成YUV420以后和原先的BMP对照,肉眼几乎分辨不出有什么失真。但是……效率太低下了。两种转换在相同的模拟器上跑,第一种大约是320--350ms,而第二种竟然达到了惊人的6000Ms.
效果对比图:

第二种(不失真,效率低)                                  第一种(失真,效率高)

接下来的时间,尽快解决第一种转换方法的偏差。

OK~没想到就用了几分钟调整了顺序,第一种方法就搞定,貌似显示的效果比第二种佳。
看图:

11.13
预览和视频捕获能支持144X176  120X160   240X320
图片拍摄就只能240X320   480X640
then,截图

抱歉!评论已关闭.