前面我写了两篇文章说明了zc301的实现 具体请看 http://blog.csdn.net/hclydao/article/details/21235919
下面顺便把通用的USB也写上 前面的ZC301获取到的格式是JPEG的所以不用进行什么处理就可以用来显示,但是标准的UVC获取到的是YUV422格式的需要转换成RGB后才能进行显示 这里我们在前面两篇的代码稍作修改就可以了
HAL层 代码如下
- /*
- * Android USB Camera zc3xx Library
- *
- * Copyright (c) 2014 Store information technology guangzhou ltd<http://www.storeinf.com>
- * Copyright (c) 2014 hclydao <hclydao@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <asm/types.h>
- #include <linux/videodev2.h>
- #include <sys/mman.h>
- #include <string.h>
- #include <malloc.h>
- #include <linux/fb.h>
- #include <jni.h>
- #include <string.h>
- #include <android/log.h>
- #include <syslog.h>
- #include <android/log.h>
- #include <android/bitmap.h>
- #define LOG_TAG "FimcGzsd"
- #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , LOG_TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , LOG_TAG, __VA_ARGS__)
- #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , LOG_TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , LOG_TAG, __VA_ARGS__)
- struct fimc_buffer {
- unsigned char *start;
- size_t length;
- };
- static int fd = -1;
- struct fimc_buffer *buffers=NULL;
- struct v4l2_buffer v4l2_buf;
- static int bufnum = 1;
- static int mwidth,mheight;
- static int c_type = 0;
- int *rgb = NULL;
- int *ybuf = NULL;
- int yuv_tbl_ready=0;
- int y1192_tbl[256];
- int v1634_tbl[256];
- int v833_tbl[256];
- int u400_tbl[256];
- int u2066_tbl[256];
- /*
- *open usb camera device
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_open(JNIEnv * env, jclass obj, const jbyteArray devname)
- {
- jbyte *dev = (jbyte*)(*env)->GetByteArrayElements(env, devname, 0);
- fd = open(dev, O_RDWR, 0);
- if (fd<0)
- {
- LOGE("%s ++++ open error\n",dev);
- return -1;
- }
- (*env)->ReleaseByteArrayElements(env, devname, dev, 0);
- return fd;
- }
- /*
- * init device
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_init(JNIEnv * env, jclass obj, jint width, jint height,jint numbuf,jint ctype)
- {
- int ret;
- int i;
- bufnum = numbuf;
- mwidth = width;
- mheight = height;
- c_type = ctype;
- struct v4l2_format fmt;
- struct v4l2_capability cap;
- ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
- if (ret < 0) {
- LOGE("%d :VIDIOC_QUERYCAP failed\n",__LINE__);
- return -1;
- }
- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
- LOGE("%d : no capture devices\n",__LINE__);
- return -1;
- }
- memset( &fmt, 0, sizeof(fmt));
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if(c_type == 1)
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- else
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
- fmt.fmt.pix.width = width;
- fmt.fmt.pix.height = height;
- if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
- {
- LOGE("++++%d : set format failed\n",__LINE__);
- return -1;
- }
- struct v4l2_requestbuffers req;
- req.count = numbuf;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- ret = ioctl(fd, VIDIOC_REQBUFS, &req);
- if (ret < 0) {
- LOGE("++++%d : VIDIOC_REQBUFS failed\n",__LINE__);
- return -1;
- }
- buffers = calloc(req.count, sizeof(*buffers));
- if (!buffers) {
- LOGE ("++++%d Out of memory\n",__LINE__);
- return -1;
- }
- for(i = 0; i< bufnum; ++i) {
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- v4l2_buf.index = i;
- ret = ioctl(fd , VIDIOC_QUERYBUF, &v4l2_buf);
- if(ret < 0) {
- LOGE("+++%d : VIDIOC_QUERYBUF failed\n",__LINE__);
- return -1;
- }
- buffers[i].length = v4l2_buf.length;
- if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- fd, v4l2_buf.m.offset)) < 0) {
- LOGE("%d : mmap() failed",__LINE__);
- return -1;
- }
- }
- rgb = (int *)malloc(sizeof(int) * (mwidth*mheight));
- ybuf = (int *)malloc(sizeof(int) * (mwidth*mheight));
- return 0;
- }
- /*
- *open usb camera device
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamon(JNIEnv * env, jclass obj)
- {
- int i;
- int ret;
- enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- for(i = 0; i< bufnum; ++i) {
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- v4l2_buf.index = i;
- ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
- if (ret < 0) {
- LOGE("%d : VIDIOC_QBUF failed\n",__LINE__);
- return ret;
- }
- }
- ret = ioctl(fd, VIDIOC_STREAMON, &type);
- if (ret < 0) {
- LOGE("%d : VIDIOC_STREAMON failed\n",__LINE__);
- return ret;
- }
- return 0;
- }
- void yuyv422toABGRY(unsigned char *src)
- {
- int width=0;
- int height=0;
- width = mwidth;
- height = mheight;
- int frameSize =width*height*2;
- int i;
- if((!rgb || !ybuf)){
- return;
- }
- int *lrgb = NULL;
- int *lybuf = NULL;
- lrgb = &rgb[0];
- lybuf = &ybuf[0];
- if(yuv_tbl_ready==0){
- for(i=0 ; i<256 ; i++){
- y1192_tbl[i] = 1192*(i-16);
- if(y1192_tbl[i]<0){
- y1192_tbl[i]=0;
- }
- v1634_tbl[i] = 1634*(i-128);
- v833_tbl[i] = 833*(i-128);
- u400_tbl[i] = 400*(i-128);
- u2066_tbl[i] = 2066*(i-128);
- }
- yuv_tbl_ready=1;
- }
- for(i=0 ; i<frameSize ; i+=4){
- unsigned char y1, y2, u, v;
- y1 = src[i];
- u = src[i+1];
- y2 = src[i+2];
- v = src[i+3];
- int y1192_1=y1192_tbl[y1];
- int r1 = (y1192_1 + v1634_tbl[v])>>10;
- int g1 = (y1192_1 - v833_tbl[v] - u400_tbl[u])>>10;
- int b1 = (y1192_1 + u2066_tbl[u])>>10;
- int y1192_2=y1192_tbl[y2];
- int r2 = (y1192_2 + v1634_tbl[v])>>10;
- int g2 = (y1192_2 - v833_tbl[v] - u400_tbl[u])>>10;
- int b2 = (y1192_2 + u2066_tbl[u])>>10;
- r1 = r1>255 ? 255 : r1<0 ? 0 : r1;
- g1 = g1>255 ? 255 : g1<0 ? 0 : g1;
- b1 = b1>255 ? 255 : b1<0 ? 0 : b1;
- r2 = r2>255 ? 255 : r2<0 ? 0 : r2;
- g2 = g2>255 ? 255 : g2<0 ? 0 : g2;
- b2 = b2>255 ? 255 : b2<0 ? 0 : b2;
- *lrgb++ = 0xff000000 | b1<<16 | g1<<8 | r1;
- *lrgb++ = 0xff000000 | b2<<16 | g2<<8 | r2;
- if(lybuf!=NULL){
- *lybuf++ = y1;
- *lybuf++ = y2;
- }
- }
- }
- void
- Java_com_dao_usbcam_Fimcgzsd_pixeltobmp( JNIEnv* env,jobject thiz,jobject bitmap){
- jboolean bo;
- AndroidBitmapInfo info;
- void* pixels;
- int ret;
- int i;
- int *colors;
- int width=0;
- int height=0;
- if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
- LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
- return;
- }
- width = info.width;
- height = info.height;
- if(!rgb || !ybuf) return;
- if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
- LOGE("Bitmap format is not RGBA_8888 !");
- return;
- }
- if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
- LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
- }
- colors = (int*)pixels;
- int *lrgb =NULL;
- lrgb = &rgb[0];
- for(i=0 ; i<width*height ; i++){
- *colors++ = *lrgb++;
- }
- AndroidBitmap_unlockPixels(env, bitmap);
- }
- void yuyv422torgb(unsigned char *src,unsigned int *mrgb)
- {
- int width=0;
- int height=0;
- width = mwidth;
- height = mheight;
- int frameSize =width*height*2;
- int i;
- if((!rgb || !ybuf)){
- return;
- }
- int *lrgb = NULL;
- int *lybuf = NULL;
- lrgb = mrgb;
- lybuf = &ybuf[0];
- if(yuv_tbl_ready==0){
- for(i=0 ; i<256 ; i++){
- y1192_tbl[i] = 1192*(i-16);
- if(y1192_tbl[i]<0){
- y1192_tbl[i]=0;
- }
- v1634_tbl[i] = 1634*(i-128);
- v833_tbl[i] = 833*(i-128);
- u400_tbl[i] = 400*(i-128);
- u2066_tbl[i] = 2066*(i-128);
- }
- yuv_tbl_ready=1;
- }
- for(i=0 ; i<frameSize ; i+=4){
- unsigned char y1, y2, u, v;
- y1 = src[i];
- u = src[i+1];
- y2 = src[i+2];
- v = src[i+3];
- int y1192_1=y1192_tbl[y1];
- int r1 = (y1192_1 + v1634_tbl[v])>>10;
- int g1 = (y1192_1 - v833_tbl[v] - u400_tbl[u])>>10;
- int b1 = (y1192_1 + u2066_tbl[u])>>10;
- int y1192_2=y1192_tbl[y2];
- int r2 = (y1192_2 + v1634_tbl[v])>>10;
- int g2 = (y1192_2 - v833_tbl[v] - u400_tbl[u])>>10;
- int b2 = (y1192_2 + u2066_tbl[u])>>10;
- r1 = r1>255 ? 255 : r1<0 ? 0 : r1;
- g1 = g1>255 ? 255 : g1<0 ? 0 : g1;
- b1 = b1>255 ? 255 : b1<0 ? 0 : b1;
- r2 = r2>255 ? 255 : r2<0 ? 0 : r2;
- g2 = g2>255 ? 255 : g2<0 ? 0 : g2;
- b2 = b2>255 ? 255 : b2<0 ? 0 : b2;
- *lrgb++ = 0xff000000 | b1<<16 | g1<<8 | r1;
- *lrgb++ = 0xff000000 | b2<<16 | g2<<8 | r2;
- if(lybuf!=NULL){
- *lybuf++ = y1;
- *lybuf++ = y2;
- }
- }
- }
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_yuvtorgb(JNIEnv * env, jclass obj,const jbyteArray yuvdata, jintArray rgbdata)
- {
- jbyte *ydata = (jbyte*)(*env)->GetByteArrayElements(env, yuvdata, 0);
- jint *rdata = (jint*)(*env)->GetIntArrayElements(env, rgbdata, 0);
- yuyv422torgb(ydata,rdata);
- (*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);
- (*env)->ReleaseIntArrayElements(env, rgbdata, rdata, 0);
- return 0;
- }
- /*
- *get one frame data
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_dqbuf(JNIEnv * env, jclass obj,const jbyteArray videodata)
- {
- int ret;
- jbyte *data = (jbyte*)(*env)->GetByteArrayElements(env, videodata, 0);
- v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- ret = ioctl(fd, VIDIOC_DQBUF, &v4l2_buf);
- if (ret < 0) {
- LOGE("%s : VIDIOC_DQBUF failed, dropped frame\n",__func__);
- return ret;
- }
- if(c_type == 1)
- yuyv422toABGRY((unsigned char *)buffers[v4l2_buf.index].start);
- memcpy(data,buffers[v4l2_buf.index].start,buffers[v4l2_buf.index].length);
- (*env)->ReleaseByteArrayElements(env, videodata, data, 0);
- return v4l2_buf.index;
- }
- /*
- *put in frame buffer to queue
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_qbuf(JNIEnv * env, jclass obj,jint index)
- {
- int ret;
- v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- v4l2_buf.index = index;
- ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
- if (ret < 0) {
- LOGE("%s : VIDIOC_QBUF failed\n",__func__);
- return ret;
- }
- return 0;
- }
- /*
- *streamoff
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamoff(JNIEnv * env, jclass obj,jint index)
- {
- enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- int ret;
- ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
- if (ret < 0) {
- LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__);
- return ret;
- }
- return 0;
- }
- /*
- *release
- */
- JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_release(JNIEnv * env, jclass obj)
- {
- enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- int ret;
- int i;
- ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
- if (ret < 0) {
- LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__);
- return ret;
- }
- for (i = 0; i < bufnum; i++) {
- ret = munmap(buffers[i].start, buffers[i].length);
- if (ret < 0) {
- LOGE("%s : munmap failed\n",__func__);
- return ret;
- }
- }
- free (buffers);
- if(rgb) free(rgb);
- if(ybuf) free(ybuf);
- close(fd);
- return 0;
- }
yuyv422toABGRY 这个是yuv转rgb
Java_com_dao_usbcam_Fimcgzsd_pixeltobmp 这个是rgb转bitmap
这两个函数是我在网上找到例子simplewebcam里拷出来的
同时Android.mk修改如下
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := fimcgzsd
- LOCAL_SRC_FILES := fimcgzsd.c
- LOCAL_LDLIBS := -llog -ljnigraphics
- include $(BUILD_SHARED_LIBRARY)
- # The ARMv7 is significanly faster due to the use of the hardware FPU
- APP_ABI := armeabi armeabi-v7a
- APP_PLATFORM := android-8
应用层
增加一个c_type指定是zc301还是uvc 我还是把代码贴上来吧
- package com.dao.usbcam;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.ImageFormat;
- import android.graphics.Rect;
- import android.graphics.YuvImage;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.text.format.Time;
- import android.view.Menu;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.Window;
- import android.view.WindowManager;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.Toast;
- public class MainActivity extends Activity {
- private ImageView mImag;
- private int width = 320;
- private int height = 240;
- private String devname = "/dev/video3";
- private byte[] mdata;
- private Handler mHandler;
- private int numbuf = 0;
- private int index = 0;
- private int ret = 0;
- private int ctype = 1;//0 is zc301 1 is uvc camera
- public Button mcap;
- private Bitmap bitmap;
- private Bitmap bmp;
- private int[] rgb;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- setContentView(R.layout.activity_main);
- mImag = (ImageView)findViewById(R.id.mimg);
- mcap = (Button)findViewById(R.id.mcap);
- bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- numbuf = 4;
- mdata = new byte[width * height * numbuf];
- rgb = new int[width * height * numbuf];
- ret = Fimcgzsd.open(devname.getBytes());
- if(ret < 0)
- finish();
- ret = Fimcgzsd.init(width, height, numbuf,ctype);
- if(ret < 0)
- finish();
- ret = Fimcgzsd.streamon();
- if(ret < 0)
- finish();
- mHandler = new Handler();
- new StartThread().start();
- mcap.setOnClickListener(new CaptureListener());
- }
- final Runnable mUpdateUI = new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- mImag.setImageBitmap(bitmap);
- }
- };
- class StartThread extends Thread {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- //super.run();
- while(true) {
- if(ctype == 1){
- index = Fimcgzsd.dqbuf(mdata);
- if((index < 0) || (mdata == null)) {
- onDestroy();
- break;
- }
- Fimcgzsd.pixeltobmp(bmp);
- mHandler.post(mUpdateUI);
- bitmap = bmp;
- Fimcgzsd.qbuf(index);
- //Fimcgzsd.yuvtorgb(mdata, rgb);
- //mHandler.post(mUpdateUI);
- //bitmap = Bitmap.createBitmap(rgb,width,height,Bitmap.Config.ARGB_8888);
- //Fimcgzsd.qbuf(index);
- } else {
- index = Fimcgzsd.dqbuf(mdata);
- if(index < 0) {
- onDestroy();
- break;
- }
- mHandler.post(mUpdateUI);
- bitmap = BitmapFactory.decodeByteArray(mdata, 0, width * height);
- Fimcgzsd.qbuf(index);
- }
- }
- }
- }
- public static void saveMyBitmap(Bitmap mBitmap) {
- Time mtime = new Time();
- mtime.setToNow();
- File fdir = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "/gzsd/");
- if(!fdir.exists()) {
- fdir.mkdir();
- }
- File f = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "/gzsd/" + mtime.year + mtime.month + mtime.monthDay + mtime.hour + mtime.minute +mtime.second+".png");
- try {
- f.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- FileOutputStream fOut = null;
- try {
- fOut = new FileOutputStream(f);
- mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
- fOut.flush();
- fOut.close();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- class CaptureListener implements OnClickListener{
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- //new CapThread().start();
- //Fimcgzsd.streamoff();
- saveMyBitmap(bitmap);
- //Fimcgzsd.streamon();
- Toast.makeText(MainActivity.this, "Capture Successfully", Toast.LENGTH_SHORT).show();
- }
- }
- class CapThread extends Thread {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- //super.run();
- saveMyBitmap(bitmap);
- Toast.makeText(MainActivity.this, "Capture Successfully", Toast.LENGTH_LONG).show();
- }
- }
- @Override
- protected void onStop() {
- // TODO Auto-generated method stub
- super.onStop();
- Fimcgzsd.release();
- finish();
- }
- @Override
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- Fimcgzsd.release();
- finish();
- }
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- super.onDestroy();
- Fimcgzsd.release();
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.main, menu);
- finish();
- return true;
- }
- }
感觉有点 模糊 我发现拿来自拍 效果还不错 模糊产生美 哈哈..