音视频技术开发--V4L2学习(二)

接上篇《音视频技术开发--V4L2学习(一)》

三、 V4L2 Sample增加正确的色彩格式

首先接上面运行sample,运行画面花屏问题,怀疑是UVC采集的不是YUV420,我们尝试改成其他像素格式试试。

打卡代码的capturer_mmap.c文件,可以看到sample里面只有三种格式(如下图),我们增加YUV422(实际测试接的UVC只支持YVYU格式)试试。

音视频技术开发--V4L2学习(二)

 在/usr/include/linux/videodev2.h头文件中,包含了像素格式的定义。我们这边选择YVYU格式,增加到capturer_mmap.c;

音视频技术开发--V4L2学习(二)

 对capturer_mmap.c的修改,主要为:

1、增加YVYU色彩格式,命令行-p 3时,使用该格式通过V4L2配置到UVC;

2、修改对应的每帧读取大小;

[root@localhost V4l2_samples-0.4.1]# diff capturer_mmap.c capturer_mmap.c.bak 
98,100d97
<         case 3:
<             Bpf = width*height*2;
<         break;
336,338d332
<             break;
<         case 3:
<             fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YVYU;

通过以上修改,capturer_mmap程序读出来正确的YVYU采集数据;

之后相应得修改viewer.c,使之正确显示YVYU格式,修改如下:

[root@localhost V4l2_samples-0.4.1]# diff viewer.c viewer.c.bak 
220,298d219
< //read the data from memory, converts that data to RGB, and call Put (shows the picture) 
< static void process_image_yuv422 (uint8_t * videoFrame,  image_context image_ctx, int width, int height)
< {
<     XImage * xImage1 = image_ctx.xImage;
<     uint8_t * imageLine1;
<     int    xx,yy;
<     int    x,y;
<     int bpl,Bpp,amp;
<     double r,g,b;
<     unsigned char Y,U,V;
<     unsigned char R,G,B,RG,GB;
<     imageLine1 = (uint8_t *) xImage1->data;
<     bpl=xImage1->bytes_per_line;
<     Bpp=xImage1->bits_per_pixel/8;
<     int ret;
< 
<     ret = read(STDIN_FILENO, videoFrame , width*height*2);
<     
<     switch (xImage1->depth)
<     {
<         case 16://process one entire frame
<             for (yy = 0; yy < (height); yy++)
<             {
<                 for (xx =0; xx < (width/2); xx++)
<                 {
<                     //in every loop 2 pixels are processed   
<                     V = videoFrame[(width*2*y)+(1*x+1)];
<                     U = videoFrame[(width*2*y)+(1*x+3)];
< 
<                     Y = videoFrame[(width*2*y)+(1*x)];
<                     yuv_to_rgb_16(Y, U, V, &RG, &GB);
<                     imageLine1[(bpl*y)+(Bpp*x)]=GB;
<                     imageLine1[(bpl*y)+(Bpp*x)+1]=RG;
< 
<                     Y = videoFrame[(width*2*y)+(1*(x+2))];
<                     yuv_to_rgb_16(Y, U, V, &RG, &GB);
<                     imageLine1[(bpl*y)+(Bpp*(x+1))]=GB;
<                     imageLine1[(bpl*y)+(Bpp*(x+1))+1]=RG;
<                 }
<             }
<             break;
<             
<         case 24:
<             for (yy = 0; yy < (height); yy++)
<             {
<                 for (xx =0; xx < (width/2); xx++)
<                 {
<                     x=2*xx;
<                     y=yy;
<                     
<                     //in every loop 2 pixels are processed   
<                     V = videoFrame[(width*2*y)+(2*x+1)];
<                     U = videoFrame[(width*2*y)+(2*x+3)];
< 
<                     Y = videoFrame[(width*2*y)+(2*x)];
<                     yuv_to_rgb_24(Y, U, V, &R, &G, &B);
<                     imageLine1[(bpl*y)+(Bpp*x)]=B;
<                     imageLine1[(bpl*y)+(Bpp*x)+1]=G;
<                     imageLine1[(bpl*y)+(Bpp*x)+2]=R;
<                     
<                     Y = videoFrame[(width*2*y)+(2*(x+2))];
<                     yuv_to_rgb_24(Y, U, V, &R, &G, &B);
<                     imageLine1[(bpl*y)+(Bpp*(x+1))]=B;
<                     imageLine1[(bpl*y)+(Bpp*(x+1))+1]=G;
<                     imageLine1[(bpl*y)+(Bpp*(x+1))+2]=R;
<                 }
<             }
<             break;
<         default:
<             fprintf(stderr,"\nError: Color depth not supported\n");
<             exit(EXIT_FAILURE);
<             break;
<     }
<     image_put(image_ctx, 0, 0, 0, 0, width, height);
< 
<     if (XPending(image_ctx.display) > 0)
<         XNextEvent(image_ctx.display, image_ctx.event); //refresh the picture
< }
< 
467,468c388
<     PIX_FMT_RGB32,
<     PIX_FMT_YUYV
---
>     PIX_FMT_RGB32
778,780d697
<             break;
<             case PIX_FMT_YUYV:
<                 process_image_yuv422 (videoFrame, img_ctx, width, height);

make后执行命令: ./capturer_mmap -D /dev/video0 -w 640*480 -p 3 | ./viewer -w 640*480 -p 3;可以看到测试画面播放显示正常。

音视频技术开发--V4L2学习(二)

 

上一篇:Linux驱动V4L2摄像头


下一篇:[Linux 基础] -- V4L2 框架分析