开启视频功能运行linphonec -V以段错误结束,由于视频通话的视频部分分为捕获视频和显示视频,捕获由V4L2完成、显示由SDL完成,因此对两者分开进行测试。
测试捕获功能并开启日志linphonec -C -d 6,-C为capture捕获的意思,出现错误:libv4l2: error allocating conversion buffer,通过分析V4L2的编程过程并编写捕获测试程序以了解V4L2编程,接着对V4L2和mediastreamer的源码进行分析,定位错误原因是在对摄像头ioctl的尝试捕获格式过程中出现错误,修改源代码如下:
vi ./linphone-3.4.3/mediastreamer2/src/msv4l2.c +163
do{
fmt.fmt.pix.width = s->vsize.width;
fmt.fmt.pix.height = s->vsize.height;
if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_MJPEG)){
s->pix_fmt=MS_MJPEG;
s->int_pix_fmt=V4L2_PIX_FMT_MJPEG;
ms_message("v4lv2: MJPEG choosen");
break;
}else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_YUYV)){
s->pix_fmt=MS_YUYV;
s->int_pix_fmt=V4L2_PIX_FMT_YUYV;
ms_message("v4lv2: V4L2_PIX_FMT_YUYV choosen");
break;
}else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_RGB24)){
s->pix_fmt=MS_RGB24;
s->int_pix_fmt=V4L2_PIX_FMT_RGB24;
ms_message("v4lv2: RGB24 choosen");
break;
}else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_YUV420)){
s->pix_fmt=MS_YUV420P;
s->int_pix_fmt=V4L2_PIX_FMT_YUV420;
ms_message("v4lv2: YUV420P choosen");
break;
}else{
ms_error("Could not find supported pixel format for %ix%i", s->vsize.width, s->vsize.height);
}
s->vsize=ms_video_size_get_just_lower_than(s->vsize);
}while(s->vsize.width!=0);
由于本人的摄像头支持MJPEG和YUYV格式,故将尝试格式顺序设为如上顺序,至于为什么尝试错误的格式会出错尚未找到原因(如果您知道还请麻烦告知),因为这个功能在x86下正常工作。至此捕获功能运行正常。
关于视频的显示,通过对SDL编程的了解以及SDL下各种驱动方式的显示,我们知道x86下Linux通过X11显示,其他平台还可以通过Qtopia、fbcon等方式驱动。由于我们的Linphone是通过Qtopia调用的,便尝试了Qtopia驱动SDL的方式,经过长时间的研究和测试运行过程中由于无法探测的错误无法解决最终杀死了这种方案,最后使用直接控制framebuffer的fbcon驱动方式来显示。关于使用fbcon的SDL请参考博文:SDL及扩展库在ARM-Linux 完整移植(确保测试程序运行成功),编译过程已体现于第一篇中SDL的编译。接下来测试显示视频linphone -D -d 6,程序再次以段错误结束提示信息为:Couldn't set console screen info,分析mediastreamer和SDL源码可知错误是对framebuffer设备/dev/fb0进行ioctl时产生的,对错误在源码中进一步跟踪做如下源代码的修改:
vi ./linphone-3.4.3/mediastreamer2/src/videoout.c +299
if(fbuf->w > 320)
fbuf->w = 320;
if(fbuf->h > 240)
fbuf->h =240;
i=sdl_create_window(wd, fbuf->w, fbuf->h);
vi ./SDL-1.2.14/src/video/fbcon/SDL_fbvideo.c
+84
static const SDL_Rect checkres[] = {
// { 0, 0, 1600, 1200 },
// { 0, 0, 1408, 1056 },
// { 0, 0, 1280, 1024 },
// { 0, 0, 1152, 864 },
// { 0, 0, 1024, 768 },
// { 0, 0, 960, 720 },
// { 0, 0, 800, 600 },
// { 0, 0, 768, 576 },
// { 0, 0, 720, 576 },
// { 0, 0, 720, 480 },
// { 0, 0, 640, 480 },
// { 0, 0, 640, 400 },
// { 0, 0, 512, 384 },
{ 0, 0, 320, 240 },
{ 0, 0, 320, 200 }
};
+1063
if ( !shadow_fb &&
ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
vinfo.yres_virtual = height;
if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
SDL_SetError("Couldn't set console screen info");
// return(NULL);
}
}
vi ./SDL-1.2.14/src/video/SDL_video.c +633
if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
// flags |= SDL_HWSURFACE;
}
vi ./linphone-3.4.3/mediastreamer2/include/mediastreamer2/msvideo.h +25
将此处所有大于320x240的换为320x240
上面的源码修改加上编译过程即可在ARM9上运行了,使用的是友善之臂的Mini2440开发版及其自带的交叉编译工具链,不同的交叉编译工具,使用库和编译过程则不同。祝你好运!