java usb camera_android4.0 USB Camera实例(一)HAL层

2023-10-27

一直想自己写一个从HAL层到应用层的Camera例子,android4.0上usb camera用不了 所以决定自己写一个 usb camera和coms原理都是一样的 基本v4l2 只不过源码数据格式不一样而已 下面我们就从HAL层开始

以下是我的代码,先上代码在 一步步说明

fimcgzsd.c

/*

* Android USB Camera zc3xx Library

*

* Copyright (c) 2014 Store information technology guangzhou ltd

* Copyright (c) 2014 hclydao

*

* 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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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;

/*

*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 errorn",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)

{

int ret;

int i;

bufnum = numbuf;

mwidth = width;

mheight = height;

struct v4l2_format fmt;

struct v4l2_capability cap;

ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);

if (ret < 0) {

LOGE("%d :VIDIOC_QUERYCAP failedn",__LINE__);

return -1;

}

if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {

LOGE("%d : no capture devicesn",__LINE__);

return -1;

}

memset( &fmt, 0, sizeof(fmt));

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

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 failedn",__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 failedn",__LINE__);

return -1;

}

buffers = calloc(req.count, sizeof(*buffers));

if (!buffers) {

LOGE ("++++%d Out of memoryn",__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 failedn",__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;

}

}

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 failedn",__LINE__);

return ret;

}

}

ret = ioctl(fd, VIDIOC_STREAMON, &type);

if (ret < 0) {

LOGE("%d : VIDIOC_STREAMON failedn",__LINE__);

return ret;

}

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 framen",__func__);

return ret;

}

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 failedn",__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 failedn",__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 failedn",__func__);

return ret;

}

for (i = 0; i < bufnum; i++) {

ret = munmap(buffers[i].start, buffers[i].length);

if (ret < 0) {

LOGE("%s : munmap failedn",__func__);

return ret;

}

}

free (buffers);

close(fd);

return 0;

}

首先是open这个就不作说明了

第二初始化init函数

ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);

if (ret < 0) {

LOGE("%d :VIDIOC_QUERYCAP failedn",__LINE__);

return -1;

}

if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {

LOGE("%d : no capture devicesn",__LINE__);

return -1;

}获取设备相关信息,检查是否支持capture模式

memset( &fmt, 0, sizeof(fmt));

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

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 failedn",__LINE__);

return -1;

}设置格式,usb camera获取到的已经是jpeg格式 所以这里设置成RGB565格式

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 failedn",__LINE__);

return -1;

}申请缓冲区,这里申请numbuf个缓冲帧

buffers = calloc(req.count, sizeof(*buffers));

if (!buffers) {

LOGE ("++++%d Out of memoryn",__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 failedn",__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;

}

}映射虚拟内存到物理地址,获取每个缓冲区的物理地址

streamon函数

将缓冲区放入队列并开启数据流

dqbuf函数

获取一帧数据 返回当前缓冲区的序列号

qbuf函数

将指定缓冲区放入队列,获取到某一缓冲区的数据后需要重新将这个缓冲区放入队列

后面两个我就不多说明了

Android.mk文件:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := eng

LOCAL_SRC_FILES:= fimcgzsd.c

LOCAL_MODULE := libfimcgzsd

LOCAL_LDLIBS := -llog

LOCAL_SHARED_LIBRARIES := libc libcutils

include $(BUILD_SHARED_LIBRARY)

参考博文:https://blog.csdn.net/eastmoon502136/article/details/8190262

============================================

作者:hclydao

https://blog.csdn.net/hclydao

版权没有,但是转载请保留此段声明

============================================

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java usb camera_android4.0 USB Camera实例(一)HAL层 的相关文章

  • 怎么将将 Python 的安装目录添加到了系统的环境变量路径中

    要在 Windows 系统中将 Python 的安装目录添加到环境变量路径中 请按照以下步骤操作 1 打开 控制面板 2 选择 系统和安全 3 选择 系统 4 在 系统属性 中 选择 高级系统设置 5 在 高级 选项卡中 选择 环境变量 6
  • 【微信小程序】微信小程序支付功能实现

    1 前言 微信小程序支付 开启新一代便捷支付新时代 随着互联网技术的不断发展 微信小程序支付已经成为了人们日常生活中不可或缺的一部分 微信小程序是一种无需下载安装即可使用的应用 用户可以通过微信扫描或搜索关键词来打开并使用 而微信小程序支付
  • javascript面试题--持续更新

    前端HTML篇 前端CSS篇 Vue篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript Reac
  • pytorch量化库使用(2)

    FX Graph Mode量化模式 训练后量化有多种量化类型 仅权重 动态和静态 配置通过qconfig mapping prepare fx函数的参数 完成 FXPTQ API 示例 import torch from torch ao
  • 高可用系统的设计与维护

    author skate time 2011 02 11 高可用系统的设计与维护 对于一个高可用的系统评价 主要体现在架构 功能 性能 安全 维护 兼容性等方面 如何设计维护这样一个高可用系统的 1 一个提供7 24服务的网站架构系统 要避
  • mysql主从 读写_mysql主从-读写分离

    一个完整的MySQL读写分离环境包括以下几个部分 应用程序client database proxy database集群 在本次实战中 应用程序client基于c3p0连接后端的database proxy database proxy负
  • 最新RAD Studio 11.3亚历山大版本上市

    By Marco Cantu February 27 2023 Embarcadero很高兴地宣布RAD Studio 11 Alexandria Release 3的发布 也被称为RAD Studio 11 3 同时发布的还有Delphi
  • k8s集群PHP环境使用

    一 环境介绍 k8s版本 1 15 2 存储 阿里云NAS 测试代码 wordpress 二 下载wordpress和创建好数据库等 1 下载wordpress wget https cn wordpress org latest zh C
  • 异步的AsyncHttpClient使用详解

    背景 前面的一篇文章 同步的HttpClient使用详解 中 提到了服务端通进行网络请求的方式 也讲述了在并发量大的情况下使用HttpClient的连接池来提高性能 此方法虽然很有效果 但是当访问量极大或网络不好的情况下也会出现某些网络请求
  • HyperLPR车牌识别技术算法之车牌粗定位与训练

    关于HyperLPR HyperLPR是一个使用深度学习针对对中文车牌识别的实现 与较为流行的开源的EasyPR相比 它的检测速度和鲁棒性和多场景的适应性都要好于目前开源的EasyPR HyperLPR可以识别多种中文车牌包括白牌 新能源车
  • js分享功能

    需求 页面需要添加分享到 微博 QQ空间 等功能 具体 div class jz blog a class jiathis button qzone QQ空间 a a class jiathis button tsina 新浪微博 a a
  • Cocos Creator性能调优优化集锦

    前言 一 为什么要做性能优化 性能 是一种优秀的能力 唤醒快 运行持久 稳定 这种能力在游戏上能让你的用户感觉很爽 表征表现为加载快 手机不发热 运行流畅 不卡顿 所以 性能优化的终极目标是 让你的用户感觉很爽 当然这种爽你不能以牺牲自己为
  • Docker快速部署Hadoop环境

    Docker安装部署Hadoop环境 通过三个容器来模拟三个节点 最后只保留Master节点实现搭建 安装环境 Ubuntu 22 04 1 LTS 和Docker 23 0 1 安装过程 拉取镜像 docker pull registry
  • 计算机视觉初步认识

    计算机视觉是使用计算机及相关设备对生物视觉的一种模拟 它的主要任务就是通过对采集的图片或视频进行处理以获得相应场景的三维信息 就像人类和许多其他类生物每天所做的那样 从计算机视觉领域可以衍生出大量有用的应用程序 下面是计算机视觉应用程序的一
  • FreeRTOS记录(八、用软件定时器?还是硬件定时器?)

    FreeRTOS软件定时器 相对前面的内容来说 软件定时器还是比较简单的 我们简单测试一下 因为是简单介绍 所以原理和源码的分析不会那么详细 具体可以根据文中API查看源码 使用起来记住创建 启动 回调函数核心步骤即可 增加测试Demo 再
  • 禁止 Cookie 使用 Session,采用 URL 重写,具体解决方案

    先叙述一下 session 的实现原理吧 session 服务器为每个客户端访问开辟的一块内存区域 可以存放一些客户端的一些操作信息 正常情况下在用户通过客户端访问服务器这个过程中 session 一直存活 直到客户端关闭 服务器中的 se
  • TWS耳机充电盒芯片方案、霍尔开关+无线充接收带电量显示方案

    旭鑫胜电子TWS充电盒方案XS016 RX 专门为TWS充电盒设计的无线充电接收方案XS016 RX XS016 RX无线充电接收芯片与锂电池充电管理芯片结合 以满足无线充电盒的设计要求 功能特点 1 符合qi1 2标准协议 2 具有异物检
  • CentOS-6.6-x86_64-minimal.iso镜像下载

    链接 https pan baidu com s 1FKfIvK65KzVxV96Gns7ivA https pan baidu com s 1FKfIvK65KzVxV96Gns7ivA 提取码 zt88
  • 2.1python程序控制-选择结构

    第1关 判断奇偶 任务描述 本关任务 编写一个能判断输入数字奇偶的小程序 相关知识 为了完成本关任务 你需要掌握 python如何进行数字的读取和if else条件控制结构 Begin your code here x int input

随机推荐

  • NNDL 实验五 前馈神经网络(1)二分类任务

    pytorch实现 4 1 神经元 4 1 1 净活性值 使用pytorch计算一组输入的净活性值z 净活性值z经过一个非线性函数f 后 得到神经元的活性值a 使用pytorch计算一组输入的净活性值 代码参考paddle例题 import
  • Hexo_更换主题(Next)

    Hexo 更换主题 Next Hexo更换主题 只需要将主题文件拷贝到自己博客根目录下的themes子目录内 然后修改配置文件 即可将hexo默认的主题更换为自己想要的主题 下载Next 打开git bash here命令提示符 执行 cd
  • 初体验深信服的云桌面

    昨天上午深信服的工程师到这边来安装服务器 本想看一下具体的安装 但是上午有其他事情 没有看成 下午他给我讲了一下具体的使用 我体验了一下深信服的云桌面 总体感觉管理员的维护和客户的使用都比较方便 但是可能是服务器的配置一般 体验谈不上顺滑
  • react的生命周期

    目录 一 初始化阶段 constructor static getDerivedStateFromProps componentWillMount UNSAFE componentWillMount render componentDidM
  • pg_dump 不能用 出现pg_dump: No matching tables were found,pg_dump: schema with OID 1515227 does not exi

    使用sql查询 创建函数 直接复制即可 CREATE OR REPLACE FUNCTION public show create table in schema name varchar in table name varchar RET
  • 初步了解爆破(附Burp suite)

    huihui爆破通常是网站管理 运营人员由于安全意识不足 为了方便 避免忘记密码等 使用了非常容易记住的密码 或者是直接采用了系统的默认密码等 攻击者利用此漏洞可直接进入应用系统或者管理系统 从而进行系统 网页 数据的篡改与删除 非法获取系
  • 第十五章 Scala进阶——隐式转换与隐式参数

    考虑如下场景 假设编写了一个向量类MyVector 并且包含了一些向量的基本操作 因为向量可以与标量做数乘运算 所以需要一个计算数乘的方法 它应该接收一个类型为基本值类的参数 在向量对象myVec调用该方法时 可以写成诸如 myVec 2
  • python中time clock方法不可用的解决技巧

    Python time clock 函数以浮点数计算的秒数返回当前的CPU时间 用来衡量不同程序的耗时 比time time 更有用 这个需要注意 在不同的系统上含义不同 在UNIX系统上 它返回的是 进程时间 它是用秒表示的浮点数 时间戳
  • QT自定义信号与槽发生重载解决办法

    信号与槽作为qt中的核心机制 在qt应用开发中经常会用的 但是原生的信号与槽连接传参 只支持基本的数据类型 比如char int float double 如果想要在信号与槽之间传递自定义参数 比如结构体 类等 就必须特别注意 因为在编译的
  • shell中的常用通配符,字符类

    通配符是一种特殊语句 主要有星号 和问号 用来模糊搜索文件 当查找文件夹时 可以使用它来代替一个或多个真正字符 当不知道真正字符或者懒得输入完整名字时 常常使用通配符代替一个或多个真正的字符 shell 提供了特殊字符来帮助你快速指定一组文
  • Python TKinter 天气时钟

    用Python的tk做了一个可以用的小天气时钟软件 分享给大家啦 pageFrame from tkinter import import math time import threading as thd from getWeather
  • 免费智能机器人聊天API

    道翰天琼的免费智能机器人聊天API 认知智能CI机器人是杭州道翰天琼智能科技有限公司旗下产品 认知智能机器人是依托道翰天琼10年研发的认知智能CI体系为核心而打造的认知智能机器人大脑 是全球第一个认知智能机器人大脑 具有突破性 创新性 领航
  • 关于在VS+QtTools环境下使用QList<自定义类型>调试存在乱码问题的研究【记录】

    文章目录 前言 同事的解决方案 当结构体作用域改变时 这时我更加迷惑了但是我发现一个新的点 总结目前发现的俩种解决方案 当我不调试执行运行它它它它有又变了 初步个人结论 Qt测试结果 总结 前言 这个问题是在同事在从数据库读取数据时才发现的
  • Javaweb登录功能优化及注销登录

    登录功能优化 上篇登录功能代码在从数据库取出用户信息的代码中少写了取出用户姓名 现在将其加上user setName rs getString u name 在登录成功后右上角会有一个xx用户 我们希望把用户名字显示在xx上 所以对其adm
  • idea2021搭建SpringMVC项目

    打开IDEA 点击file gt close Project 点击完了之后跳转到idea的首页 点击New Project 左侧选择maven 在右侧勾选Create from archetype 并且选择结尾带webapp的选项的类型 然
  • Elasticsearch安装ik分词插件

    前置条件 如果发现问题请留言 如果有发现不正确的地方 欢迎留言指正 感激不尽 已安装好Elasticsearch 本次安装插件版本为7 3 1 需与elasticsearch版本一致 elasticsearch安装在 home elk el
  • Fluid主题出错解决方案

    Fluid主题排版出错 重装一次主题解决 一 存在问题 大半个月没有浏览Hexo博客 再次浏览的时候发现网页的排版布局竟然出错了 PS 导航栏排版出错 PS 内容板块的宽度失效 PS footer部分排版也出错了 打开 开发者模式 查看一下
  • k8s远程debug

    k8s远程debug 1 方案1 方案1是不行的 因为k8s的ingress走的7层协议 1 1 应用 启动debug端口 java agentlib jdwp transport dt socket server y suspend n
  • PCL点云处理之添加高斯噪点的两种方法(详细注释版)(一百八十一)

    PCL点云处理之添加高斯噪点的两种方法 详细注释版 一百八十一 一 实验效果 二 算法简介 三 具体流程 四 PCL自带函数实现 1 代码 2 结果 五 Boost函数实现 1 代码 2 结果 总结 一 实验效果 通过实验测试 效果如上所示
  • java usb camera_android4.0 USB Camera实例(一)HAL层

    一直想自己写一个从HAL层到应用层的Camera例子 android4 0上usb camera用不了 所以决定自己写一个 usb camera和coms原理都是一样的 基本v4l2 只不过源码数据格式不一样而已 下面我们就从HAL层开始