最近在开始研究V4L2应用编程,网上找来一个embedsky的应用程序进行preview,第一次打开的时候是可以正常的preview,但是再次打开的时候提示:huffman table don't exist,empty input file。
我想之所以会报错huffman table don't exist,是在下面这个判断函数中,从缓冲区取出的图像数据buffers中不符合下面这个条件,也就是缓冲区取出的数据有错
//check huffman table,these code are optional for (i1=0; i1<buf.bytesused; i1++) { if ((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4)) { break; } } if (i1 == buf.bytesused) { printf("huffman table don't exist! \n"); goto next_frame; //添加这句话表示如果huffman table don't exist的话表示采集的第一帧图像有问题,则跳转到next_frame的位置去执行 //在next_frame位置,会重新将刚才从缓冲队列中取出的数据放入缓冲队列,等待下一次被取出 }
那么我就暂时不用这次缓冲区取出的数据,重新将这个缓冲区放入到缓冲队列中去,等待下一次从缓冲队列中取出数据,解决的办法是在输出huffman table don't exist的地方让程序跳转到next_frame位置,在next_frame位置的函数将刚才取出的队列重新放入缓冲区
next_frame: //将取出的图像放回缓冲区 memset(&buf, 0 ,sizeof(buf)); buf.index = numBufs; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { printf("VIDIOC_QBUF error\n"); return -1; }
这样再次打开preview的时候还能继续preview,不知各位还有什么更好的解决办法?
下面是代码片段,完整的程序在:http://download.csdn.net/detail/luckywang1103/6664249
//预览采集到的图像 while (1) { //如果把处理JPEG格式的数据和显示程序分离,把处理JPEG部分的数据作成一个新的线程,预览时会更加流畅。 for (numBufs = 0; numBufs < req.count; numBufs++) { if ((fd_y_file = fopen(s, "wb")) < 0) { printf("Unable to create y frame recording file\n"); return -1; } memset(&buf, 0, sizeof(buf)); buf.index = numBufs; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //取得原始采集数据 buf.memory = V4L2_MEMORY_MMAP; //存储类型:V4L2_MEMORY_MMAP(内存映射)或V4L2_MEMORY_USERPTR(用户指针) if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) //从缓冲队列中取出数据 { perror("VIDIOC_DQBUF failed.\n"); return -1; } unsigned char *ptcur = buffers[numBufs].start; //开始霍夫曼解码 int i1; //check huffman table,these code are optional for (i1=0; i1<buf.bytesused; i1++) { if ((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4)) { break; } } if (i1 == buf.bytesused) { printf("huffman table don't exist! \n"); goto next_frame; } int i; //SOI = Start Of Image = "FFD8", EOI = End Of Image = "FFD9" for (i=0; i<buf.bytesused; i++) { if ((buffers[numBufs].start[i] == 0x000000FF) && (buffers[numBufs].start[i+1] == 0x000000D8)) break; ptcur++; } int imagesize = buf.bytesused - i; fwrite(ptcur, imagesize, 1, fd_y_file); //开始向LCD发送数据显示采集到的图像 fclose(fd_y_file); if ((infile = fopen(s, "rb")) == NULL) { fprintf(stderr, "open %s failed\n", s); exit(-1); } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); //导入要解压的Jpeg文件infile jpeg_stdio_src(&cinfo, infile); //读取jpeg文件的文件头 jpeg_read_header(&cinfo, TRUE); //开始解压Jpeg文件,解压后将分配给scanline缓冲区, jpeg_start_decompress(&cinfo); buffer = (unsigned char *) malloc(cinfo.output_width * cinfo.output_components); y = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &buffer, 1); if (fbdev.fb_bpp == 16) { unsigned short color; for (x = 0; x < cinfo.output_width; x++) { color = RGB888toRGB565(buffer[x * 3],buffer[x * 3 + 1], buffer[x * 3 + 2]); fb_pixel(fbdev.fb_mem, fbdev.fb_width, fbdev.fb_height, x, y, color);/// } } else if (fbdev.fb_bpp == 24) { memcpy((unsigned char *)fbdev.fb_mem + y * fbdev.fb_width * 3, buffer, cinfo.output_width * cinfo.output_components); } y++;//下一个scanline } //完成Jpeg解码,释放Jpeg文件 jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); //释放帧缓冲区 free(buffer); //关闭Jpeg输入文件 fclose(infile); next_frame: //将取出的图像放回缓冲区 memset(&buf, 0 ,sizeof(buf)); buf.index = numBufs; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { printf("VIDIOC_QBUF error\n"); return -1; } } //printf("start the next frame\n"); if(stop_flag) break; }