您的位置:首页 > 其它

gspca在arm平台上的开发详解

2010-05-18 09:37 148 查看

gspca在arm平台上的开发详解

在上一篇中笔者介绍了gspca在arm平台上的移植过程,如有不清楚的可以再仔细研究一下:

http://blog.suraid.cn/index.php/2008/09/gspca-arm-compile/

这一篇中,笔者将结合中星微的zc301p芯片摄像头,带你走进gspca的源码世界!

笔者建议使用Source Insight这款软件来阅读代码,能够提高不少的工作效率。

进入gspca文件夹,我们可以看到目录结构如下:

│ changelog
│ cutlog.py
│ gspca.h
│ gspca_build
│ gspca_core.c
│ license
│ Makefile
│ Makefile.kld
│ READ_AND_INSTALL

├─Conexant
│ cx11646.h
│ cxlib.h

├─decoder
│ gspcadecoder-OSX.c
│ gspcadecoder-OSX.h
│ gspcadecoder.c
│ gspcadecoder.h

├─Etoms
│ et61xx51.h

├─Mars-Semi
│ mr97311.h

├─Pixart
│ pac207-OSX.h
│ pac207.h
│ pac7311.h

├─Sonix
│ sn9cxxx.h
│ sonix.h

├─Sunplus
│ spca501.dat
│ spca501_init-OSX.h
│ spca501_init.h
│ spca505.dat
│ spca505_init.h
│ spca506.h
│ spca508.dat
│ spca508_init-OSX.h
│ spca508_init.h
│ spca561-OSX.h
│ spca561.h

├─Sunplus-jpeg
│ jpeg_qtables.h
│ sp5xxfw2.dat
│ sp5xxfw2.h
│ spca500.dat
│ spca500_init.h

├─Transvision
│ tv8532.h

├─utils
│ spcaCompat.h
│ spcagamma.h
│ spcausb.h

└─Vimicro
cs2102.h
hdcs2020.h
hv7131b.h
hv7131c.h
icm105a.h
mc501cb.h
ov7620.h
ov7630c.h
pas106b.h
pb0330.h
tas5130c.h
tas5130c_vf0250.h
vc032x.h
vc032x_sensor.h
zc3xx.h

根目录下的源代码文件主要有两个:gspca.h和gspca_core.c。

gspca.h这个头文件主要是基于SPCA50x的,定义了一些图片信息,传感器信息,和主要的结构体信息。

gspca_core.c,看名字就知道这个文件很核心很重要,没错,这个文件就是驱动程序的主要接口,gspca是基于USB摄像头驱动的,所以你会看到usb_register,usb_deregister等字样。最后在这个文件中和我们有点关系的就数带有list字样的结构体了,它们定义了gspca支持的所有的摄像头名称,让我们来找找中星微的这款芯片啊~

static struct cam_list clist[] = {
{UnknownCamera, “Unknown”},
{IntelPCCameraPro, “Intel PC Camera Pro”},
{IntelCreateAndShare, “Intel Create and Share”},
{GrandtecVcap, “Grandtec V.cap”},
{ViewQuestM318B, “ViewQuest M318B”},
{ViewQuestVQ110, “ViewQuest VQ110″},
{KodakDVC325, “Kodak DVC-325″},
{MustekGsmartMini2, “Mustek gSmart mini 2″},
{MustekGsmartMini3, “Mustek gSmart mini 3″},
{CreativePCCam300, “Creative PC-CAM 300″},
{DLinkDSC350, “D-Link DSC-350″},
{CreativePCCam600, “Creative PC-CAM 600″},
{IntelPocketPCCamera, “Intel Pocket PC Camera”},
{IntelEasyPCCamera, “Intel Easy PC Camera”},
{ThreeComHomeConnectLite, “3Com Home Connect Lite”},
{KodakEZ200, “Kodak EZ200″},
{MaxellMaxPocket, “Maxell Max Pocket LEdit. 1.3 MPixels”},
{AiptekMiniPenCam2, “Aiptek Mini PenCam 2 MPixels”},
{AiptekPocketDVII, “Aiptek PocketDVII 1.3 MPixels”},
{AiptekPenCamSD, “Aiptek Pencam SD 2 MPixels”},
{AiptekMiniPenCam13, “Aiptek mini PenCam 1.3 MPixels”},
{MustekGsmartLCD3, “Mustek Gsmart LCD 3″},
{MustekMDC5500Z, “Mustek MDC5500Z”},
{MegapixV4, “Megapix V4″},
{AiptekPocketDV, “Aiptek PocketDV “},
{HamaUSBSightcam, “Hama USB Sightcam 100″},
{Arowana300KCMOSCamera, “Arowana 300K CMOS Camera”},
{MystFromOriUnknownCamera, “Unknow Ori Camera”},
{AiptekPocketDV3100, “Aiptek PocketDV3100+ “},
{AiptekPocketCam3M, “Aiptek PocketCam 3 M “},
{GeniusVideoCAMExpressV2, “Genius VideoCAM Express V2″},
{Flexcam100Camera, “Flexcam 100 Camera”},
{MustekGsmartLCD2, “Mustek Gsmart LCD 2″},
{PureDigitalDakota, “Pure Digital Dakota”},
{PetCam, “PetCam”},
{BenqDC1500, “Benq DC1500″},
{LogitechClickSmart420, “Logitech Inc. ClickSmart 420″},
{LogitechClickSmart510, “Logitech Inc. ClickSmart 510″},
{BenqDC1300, “Benq DC1300″},
{HamaUSBSightcam2, “Hama USB Sightcam 100 (2)”},
{MustekDV3000, “Mustek DV 3000″},
{CreativePccam750, “Creative PCcam750″},
{MaxellCompactPM3, “Maxell Compact PC PM3″},
{BenqDC3410, “Benq DC3410″},
{BenqDC1016, “Benq DC1016″},
{MicroInnovationIC200, “Micro Innovation IC200″},
{LogitechTraveler, “Logitech QuickCam Traveler”},
{Flycam100Camera, “FlyCam Usb 100″},
{UsbGrabberPV321c, “Usb Grabber PV321c”},
{ADSInstantVCD, “ADS Instant VCD”},
{Gsmartmini, “Mustek Gsmart Mini”},
{Jenoptikjdc21lcd, “Jenoptik DC 21 LCD”},
{LogitechClickSmart310, “Logitech ClickSmart 310″},
{Terratec2move13, “Terratec 2 move 1.3″},
{MustekDV4000, “Mustek DV4000 Mpeg4″},
{AiptekDV3500, “Aiptek DV3500 Mpeg4″},
{LogitechClickSmart820, “Logitech ClickSmart 820″},
{Enigma13, “Digital Dream Enigma 1.3″},
{Sonix6025, “Xcam Shanga”},
{Epsilon13, “Digital Dream Epsilon 1.3″},
{Nxultra, “Creative Webcam NX ULTRA”},
{AiptekPocketCam2M, “Aiptek PocketCam 2Mega”},
{DeMonUSBCapture, “3DeMON USB Capture”},
{CreativeVista, “Creative Webcam Vista”},
{PolaroidPDC2030, “Polaroid PDC2030″},
{CreativeNotebook, “Creative Notebook PD1171″},
{CreativeMobile, “Creative Mobile PD1090″},
{LabtecPro, “Labtec Webcam Pro”},
{MustekWcam300A, “Mustek Wcam300A”},
{GeniusVideoCamV2, “Genius Videocam V2″},
{GeniusVideoCamV3, “Genius Videocam V3″},
{GeniusVideoCamExpressV2b, “Genius Videocam Express V2 Firmware 2″},
{CreativeNxPro, “Creative Nx Pro”},
{Sonix6029, “Sonix sn9c10x + Pas106 sensor”},
{Vimicro, “Z-star Vimicro zc0301p”},……

最后一行,看见了么?这就说明这款芯片是直接能被驱动所支持的。如果读者不幸用了一款没有在这个列表中出现的摄像头怎么办?那就只好自己加进去了,然后参考和你的摄像头相类似的产品。

根目录下有很多相应芯片的文件夹,我们自然是进Vimicro了,进去后找到zc3xx.h,和我们的芯片所有相关的设置和操作都在这个文件里了,好了,我们赶紧打开看看吧。打开后,我们发现很多可以设置参数的函数,比如可以设置brightness, contrast, colors, autobright等等,但是这些函数大多数都不需要更改,除非有什么特殊需求,惟一可能需要关心一下的就是jpeg的压缩率。大家都知道zc301p可以直接产生出jpeg流,那么设置压缩率就显得十分重要。gspca中主要由zc3xx_setquality函数来设置压缩率,你可以通过在zc3xx_config函数里设置spca50x->qindex来实现,默认值为1。

接下来我们一起来看看gspca中最重要的解压缩的部分。在根目录下有个decoder文件夹,里面比较重要的文件是gspcadecoder.c,让我们来看一下。

它在开头分别定义了JPEG头的长度:

#define JPEGHEADER_LENGTH 589

JPEG头:

const unsigned char JPEGHeader[JPEGHEADER_LENGTH] = {
0xff, 0xd8, 0xff, 0xdb, 0×00, 0×84, 0×00, 0×06, 0×04, 0×05, 0×06,
0×05, 0×04, 0×06, 0×06, 0×05,
0×06, 0×07, 0×07, 0×06, 0×08, 0×0a, 0×10, 0×0a, 0×0a, 0×09, 0×09,
0×0a, 0×14, 0×0e, 0×0f, 0×0c,
0×10, 0×17, 0×14, 0×18, 0×18, 0×17, 0×14, 0×16, 0×16, 0×1a, 0×1d,
0×25, 0×1f, 0×1a, 0×1b, 0×23,……

哈夫曼表:

#define GSMART_JPG_HUFFMAN_TABLE_LENGTH 0×1A0

const unsigned char GsmartJPEGHuffmanTable[GSMART_JPG_HUFFMAN_TABLE_LENGTH]
= {
0×00, 0×00, 0×01, 0×05, 0×01, 0×01, 0×01, 0×01, 0×01, 0×01, 0×00,
0×00, 0×00, 0×00, 0×00, 0×00,
0×00, 0×00, 0×01, 0×02, 0×03, 0×04, 0×05, 0×06, 0×07, 0×08, 0×09,
0×0A, 0×0B, 0×01, 0×00, 0×03,
0×01, 0×01, 0×01, 0×01, 0×01, 0×01, 0×01, 0×01, 0×01, 0×00, 0×00,
0×00, 0×00, 0×00, 0×00, 0×01,……

量化表:

const unsigned char GsmartQTable[][64] = {

//index0,Q40
{
20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50,
33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64,
70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101,
109,……

熟悉JPEG编解码的朋友肯定知道这些都是组成一张JPEG图片的必备信息,关于JPEG笔者就不在这里详细阐述了。

int spca50x_outpicture(struct spca50x_frame *myframe)

这个函数是输出图片的接口,它会根据原数据流的格式和你所要求的输出格式来进行相应的处理,比如:

case JPGH:
width = (myframe->data[10] << 8) | myframe->data[11];
height = (myframe->data[12] << 8) | myframe->data[13];
PDEBUG(1, “Decoder find WidthxHeight %dx%d”, width,height);
/* some camera did not respond with the good height ie:Labtec Pro 240 -> 232 */
if (myframe->hdrwidth != width)
done = ERR_CORRUPTFRAME;
else {
// reset info.dri
myframe->decoder->info.dri = 0;
memcpy(myframe->tmpbuffer, myframe->data + 16,
myframe->scanlength - 16);
if (myframe->format == VIDEO_PALETTE_JPEG)
done = make_jpeg(myframe);
else
done = jpeg_decode422(myframe, bgr);
}
break;

这就是zc301p要进入的处理分支,myframe->cameratype是原始数据的格式,myframe->format是输出数据的格式。我们可以看到,如果是JPEG的话那么就执行make_jpeg,否则就执行jpeg_decode422。

接下来我们主要来分析一下make_jpeg函数:

static int make_jpeg(struct spca50x_frame *myframe)
{
__u8 *start;
int i;
__u8 value;
int width = myframe->hdrwidth;
int height = myframe->hdrheight;
long inputsize = myframe->scanlength;
__u8 *buf = myframe->tmpbuffer;
__u8 *dst = myframe->data; //这个是原始数据的地址
start = dst;
/* 设置默认的JPEG头 */
memcpy(dst, JPEGHeader, JPEGHEADER_LENGTH);
/* 设置量化表 */
*(dst + 6) = 0;
memcpy(dst + 7, myframe->decoder->quant[0], 64);
*(dst + 7 + 64) = 1;
memcpy(dst + 8 + 64, myframe->decoder->quant[1], 64);

*(dst + 564) = width & 0xFF; //图片宽的低字节位
*(dst + 563) = width >> 8 & 0xFF; //图片宽的高字节位
*(dst + 562) = height & 0xFF; //图片高的低字节位
*(dst + 561) = height >> 8 & 0xFF; //图片宽的高字节位
/* 设置图片格式 */
if (myframe->cameratype == JPEG) {
*(dst + 567) = 0×22;
dst += JPEGHEADER_LENGTH;
for (i = 0; i < inputsize; i++) {
value = *(buf + i) & 0xFF;
*dst = value;
dst++;
if (value == 0xFF) {
*dst = 0;
dst++;
}
}
} else {
*(dst + 567) = 0×21;
dst += JPEGHEADER_LENGTH;
memcpy(dst, buf, inputsize);
dst += inputsize;
}
/* 增加JPEG结尾标志 */
*(dst++) = 0xFF;
*(dst++) = 0xD9;
myframe->scanlength = (long) (dst - start);
return 0;
}

好了,这样,一个JPEG文件就可以成功的输出了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: