USBcamera 之 jni

wfliao@Precision-M6700:~/workspace/uvc/usbcam/jni$ tree 
.
├── Android.mk
├── Application.mk
└── USBcamera.c


0 directories, 3 files



wfliao@Precision-M6700:~/workspace/uvc/usbcam/jni$ cat Android.mk  
LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)
LOCAL_MODULE    := USBcamera
LOCAL_SRC_FILES := USBcamera.c
LOCAL_LDLIBS    := -llog -ljnigraphics
LOCAL_SHARED_LIBRARIES := \
     libutils \
 liblog
include $(BUILD_SHARED_LIBRARY)


wfliao@Precision-M6700:~/workspace/uvc/usbcam/jni$ cat Application.mk 
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8




wfliao@Precision-M6700:~/workspace/uvc/usbcam/jni$ cat USBcamera.c 

#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    "USBcamera"
#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_uvc_usbcam_USBcamera_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
 * 获取设备相关信息,检查是否支持capture模式
 */
JNIEXPORT jint JNICALL Java_com_uvc_usbcam_USBcamera_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;
    }
    // 获取设备相关信息,检查是否支持capture模式
    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        LOGE("%d : no capture devices\n",__LINE__);
        return -1;
    }

    //设置格式,usb camera获取到的已经是jpeg格式 所以这里设置成RGB565格式
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;
}


    //申请缓冲区,这里申请numbuf个缓冲帧
    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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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_uvc_usbcam_USBcamera_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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值