#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h> /* for videodev2.h */
#include <linux/videodev2.h>
#include "Camera.h"
int Camera::convert_yuv_to_rgb_pixel(int y, int u, int v)
{
unsigned int pixel32 = 0;
unsigned char *pixel = (unsigned char *)&pixel32;
int r, g, b;
r = y + (1.370705 * (v-128));
g = y - (0.698001 * (v-128)) - (0.337633 * (u-128));
b = y + (1.732446 * (u-128));
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
pixel[0] = r * 220 / 256;
pixel[1] = g * 220 / 256;
pixel[2] = b * 220 / 256;
return pixel32;
}
int Camera::convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
unsigned int in, out = 0;
unsigned int pixel_16;
unsigned char pixel_24[3];
unsigned int pixel32;
int y0, u, y1, v;
for(in = 0; in < width * height * 2; in += 4) {
pixel_16 =
yuv[in + 3] << 24 |
yuv[in + 2] << 16 |
yuv[in + 1] << 8 |
yuv[in + 0];
y0 = (pixel_16 & 0x000000ff);
u = (pixel_16 & 0x0000ff00) >> 8;
y1 = (pixel_16 & 0x00ff0000) >> 16;
v = (pixel_16 & 0xff000000) >> 24;
pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
pixel_24[0] = (pixel32 & 0x000000ff);
pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
rgb[out++] = pixel_24[0];
rgb[out++] = pixel_24[1];
rgb[out++] = pixel_24[2];
pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
pixel_24[0] = (pixel32 & 0x000000ff);
pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
rgb[out++] = pixel_24[0];
rgb[out++] = pixel_24[1];
rgb[out++] = pixel_24[2];
}
return 0;
}
Camera::Camera(char *DEV_NAME, int w, int h)//构造函数
{
dev_name=DEV_NAME;
io = IO_METHOD_MMAP;//IO_METHOD_READ;//IO_METHOD_MMAP;
cap_image_size=0;
width=w;
height=h;
}
Camera::~Camera(){
}
unsigned int Camera::getImageSize(){
return cap_image_size;
}
void Camera::CloseDevice() {
stop_capturing();
uninit_device();
close_device();
}
void Camera::errno_exit(const char * s) {
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
int Camera::xioctl(int fd, int request, void * arg) {
int r;
do
r = ioctl(fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
int Camera::read_frame(unsigned char *image) {
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) //把数据从缓存中读取出来
{
switch (errno) {
case EAGAIN:
return 0;
case EIO:
default:
errno_exit("VIDIOC_DQBUF");
}
}
assert(buf.index < CAPTURE_BUFFER_NUMBER);
memcpy((void*)image,(void*)buffers[0].start,buffers[0].length);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))//再将其入列,把数据放回缓存队列
errno_exit("VIDIOC_QBUF");
return 1;
}
void Camera::stop_capturing(void) {
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/*关闭视频采集命令*/
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
errno_exit("VIDIOC_STREAMOFF");
break;
}
}
bool Camera::start_capturing(void) {
unsigned int i;
enum v4l2_buf_type type;
for (i = 0; i < CAPTURE_BUFFER_NUMBER; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))//再将其入列,把数据放回缓存队列
return false;
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
return false;
return true;
}
void Camera::uninit_device(void) {
unsigned int i;
switch (io) {
case IO_METHOD_READ:
free(buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < CAPTURE_BUFFER_NUMBER; ++i)//释放申请的内存映射
if (-1 == munmap(buffers[i].start, buffers[i].length))
errno_exit("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < CAPTURE_BUFFER_NUMBER; ++i)
free(buffers[i].start);
break;
}
}
/*********************申请物理内存*******************************/
bool Camera::init_mmap(void) {
bool CouldSetFrameRate = false;
struct v4l2_streamparm StreamParam;
memset(&StreamParam, 0, sizeof StreamParam);
StreamParam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_PARM, &StreamParam) < 0) {
fprintf(stderr, "could not set frame rate\n");
} else {
CouldSetFrameRate = StreamParam.parm.capture.capability & V4L2_CAP_TIMEPERFRAME;
}
// map the capture buffer...
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = CAPTURE_BUFFER_NUMBER; // 缓冲区内缓冲帧的数目
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;// 缓冲帧数据格式
req.memory = V4L2_MEMORY_MMAP;//内存映射(memorymapping)方式
if(ioctl(fd, VIDIOC_REQBUFS, &req) < 0) //申请缓冲,count是申请的数量
{
fprintf(stderr, "request capture buffer failed\n");
return false;
}
if (int(req.count) != CAPTURE_BUFFER_NUMBER) {
fprintf(stderr, "capture buffer number is wrong\n");
return false;
}
for (unsigned int i = 0; i < req.count; i++) {
struct v4l2_buffer buf; //驱动中的一帧
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//buffer类型
buf.memory = V4L2_MEMORY_MMAP;//IO方式,内存映射
buf.index = i;//序号
//映射用户空间,把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0)
errno_exit("VIDIOC_QUERYBUF");
buffers[i].length = buf.length;
//通过mmap建立映射关系
buffers[i].start = mmap(NULL /* start anywhere */, buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */, fd, buf.m.offset);
if (MAP_FAILED == buffers[i].start)
return false;
}
return true;
}
bool Camera::init_device(void) {
v4l2_input input;
memset(&input, 0, sizeof(struct v4l2_input));
input.index = 0;
if (ioctl(fd, VIDIOC_ENUMINPUT, &input) != 0) {
fprintf(stderr, "No matching index found\n");
return false;
}
if (!input.name) {
fprintf(stderr, "No matching index found\n");
return false;
}
if (ioctl(fd, VIDIOC_S_INPUT, &input) < 0) {
fprintf(stderr, "VIDIOC_S_INPUT failed\n");
return false;
}
struct v4l2_fmtdesc fmt1; //v4l2_fmtdesc : 帧格式结构体
int ret;
memset(&fmt1, 0, sizeof(fmt1));//将fmt1结构体填充为0
fmt1.index = 0; //初始化为0,要查询的格式序号
fmt1.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt1)) == 0) //显示所有支持的格式
{
fmt1.index++;
printf("{ pixelformat = '%c%c%c%c', description = '%s' }\n",fmt1.pixelformat & 0xFF,
(fmt1.pixelformat >> 8) & 0xFF,(fmt1.pixelformat >> 16) & 0xFF,
(fmt1.pixelformat >> 24) & 0xFF,fmt1.description); // p
热爱技术。
- 粉丝: 2814
- 资源: 7860
最新资源
- 基于Beego开发的问答系统详细文档+优秀项目+全部资料.zip
- 基于beego框架的接口在线文档管理系统详细文档+优秀项目+全部资料.zip
- 基于beego框架的cms系统详细文档+优秀项目+全部资料.zip
- 基于GF(Go Frame)的后台管理系统详细文档+优秀项目+全部资料.zip
- 基于Gin + Ant Design Pro的前后端分离管理系统的前后端模块详细文档+优秀项目+全部资料.zip
- 基于Excel VBA和Go语言的自动化考试系统详细文档+优秀项目+全部资料.zip
- 基于gin+websocket+mongodb实现 IM 即时聊天系统,基于WS连接的即时聊天,支持单聊,在线回复以及历史记录查询详细文档+优秀项目+全部资料.zip
- 基于Gin + Vue + Element UI & Arco Design & Ant Design 的前后端分离权限管理系统脚手架(包含了
- 基于gin+vue+element搭建的商城管理系统详细文档+优秀项目+全部资料.zip
- 基于Go + Vue开发的管理系统脚手架, 前后端分离, 仅包含项目开发的必需部分, 基于角色的访问控制(RBAC), 分包合理, 精简易于扩展。 后端Go包含
- 基于go micro + gin + kafka + etcd的分布式消息即时通信微服务系统详细文档+优秀项目+全部资料.zip
- 基于Go + Golang + Uniapp + Vue + ElementUi + Goframe框架的新零售社交电商系统(除了go商城系统外,还有java商
- 基于Go 标准库构建的博客系统、此项目非常适合作为 Go 新手的第一个上手项目详细文档+优秀项目+全部资料.zip
- 基于go,gin,JWT,权限管理系统详细文档+优秀项目+全部资料.zip
- 基于Go Web开发实战,基于Go语言,Beego框架开发的B2C模式的电商系统详细文档+优秀项目+全部资料.zip
- 基于go、gorm、gin、mysql及layui构建的人力资源管理系统。提供员工管理、考试管理、薪资考勤管理、权限管理及分公司分库数据隔离等功能详细文档+优秀项目+全部资料.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈