Last active
April 8, 2021 14:12
-
-
Save crouchggj/6894272 to your computer and use it in GitHub Desktop.
camera v4l2 operation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ===================================================================================== | |
* | |
* Filename: camera.c | |
* | |
* Description: | |
* | |
* Version: 1.0 | |
* Created: 2013年08月23日 15时54分17秒 | |
* Revision: none | |
* Compiler: gcc | |
* | |
* Author: YOUR NAME (), | |
* Organization: | |
* | |
* ===================================================================================== | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <sys/mman.h> | |
#include <linux/videodev2.h> | |
#include <jpeglib.h> | |
#define CLEAR(x) memset(&(x),0,sizeof(x)) | |
#define MAX_WIDTH (640) | |
#define MAX_HEIGHT (480) | |
#define MAX_FPS (1) | |
extern int screen_display(char * args); | |
extern int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height); | |
int create_jpeg(unsigned char *img_src,char *filename) | |
{ | |
FILE *out; | |
struct jpeg_compress_struct jcs; | |
struct jpeg_error_mgr jem; | |
JSAMPROW row_pointer[1]; | |
jcs.err = jpeg_std_error(&jem); | |
jpeg_create_compress(&jcs); | |
out = fopen(filename,"wb"); | |
jpeg_stdio_dest(&jcs, out); | |
jcs.image_width = MAX_WIDTH; | |
jcs.image_height = MAX_HEIGHT; | |
jcs.input_components = 3; //color gray is 1 | |
jcs.in_color_space = JCS_RGB; | |
jpeg_set_defaults(&jcs); | |
jpeg_set_quality(&jcs, 80, TRUE); | |
jpeg_start_compress(&jcs, TRUE); | |
while(jcs.next_scanline < jcs.image_height){ | |
row_pointer[0] = &img_src[jcs.next_scanline*jcs.image_width*jcs.input_components]; | |
jpeg_write_scanlines(&jcs,row_pointer,1); | |
} | |
jpeg_finish_compress(&jcs); | |
jpeg_destroy_compress(&jcs); | |
fclose(out); | |
return 0; | |
} | |
int main() | |
{ | |
int ret; | |
int camera_fd; | |
camera_fd = open("/dev/video0",O_RDWR); | |
struct v4l2_fmtdesc fmt; | |
memset(&fmt,0x0,sizeof(fmt)); | |
fmt.index = 0; | |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
while ((ret = ioctl(camera_fd, VIDIOC_ENUM_FMT, &fmt)) == 0) { | |
fmt.index++; | |
printf("{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n",\ | |
fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF, \ | |
(fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF, \ | |
fmt.description); | |
} | |
struct v4l2_capability cap; | |
ret = ioctl(camera_fd, VIDIOC_QUERYCAP, &cap); | |
if(ret < 0) | |
{ | |
printf("get vidieo capability error,error code: %d \n", errno); | |
return -1; | |
} | |
printf("{ Capability: driver:'%s', card:'%s',buf_info:'%s',version:%d,capabilities:0x%x}\n",\ | |
cap.driver,cap.card,cap.bus_info,cap.version,cap.capabilities); | |
struct v4l2_format tv4l2_format; | |
CLEAR(tv4l2_format); | |
tv4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
tv4l2_format.fmt.pix.width = MAX_WIDTH; | |
tv4l2_format.fmt.pix.height = MAX_HEIGHT; | |
tv4l2_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | |
tv4l2_format.fmt.pix.field = V4L2_FIELD_INTERLACED; | |
ret = ioctl(camera_fd, VIDIOC_S_FMT, &tv4l2_format); | |
if(ret < 0) | |
{ | |
perror("VIDIOC_S_FMT"); | |
} | |
printf("{ Format width: %d, height:%d}\n",tv4l2_format.fmt.pix.width,tv4l2_format.fmt.pix.height); | |
struct v4l2_streamparm *setfps; | |
setfps = (struct v4l2_streamparm *)calloc(1,sizeof(struct v4l2_streamparm)); | |
memset(setfps,0,sizeof(struct v4l2_streamparm)); | |
setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
setfps->parm.capture.timeperframe.numerator = 1; | |
setfps->parm.capture.timeperframe.denominator = 30; | |
if(ioctl(camera_fd, VIDIOC_S_PARM,setfps) < 0) | |
{ | |
perror("VIDIOC_S_PARM"); | |
} | |
struct v4l2_requestbuffers v4l2_reqbuf; | |
memset(&v4l2_reqbuf,0,sizeof(struct v4l2_requestbuffers)); | |
v4l2_reqbuf.count = 1; | |
v4l2_reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
v4l2_reqbuf.memory = V4L2_MEMORY_MMAP; | |
ret = ioctl(camera_fd, VIDIOC_REQBUFS, &v4l2_reqbuf); | |
if(ret < 0) | |
perror("VIDIOC_REQBUFS"); | |
printf("{ Reqbuffer count: %d}\n",v4l2_reqbuf.count); | |
struct v4l2_buffer map_buffer; | |
map_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
map_buffer.index = 0; | |
map_buffer.memory = V4L2_MEMORY_MMAP; | |
ret = ioctl(camera_fd,VIDIOC_QUERYBUF,&map_buffer); | |
if(ret < 0) | |
perror("VIDIOC_QUERYBUF"); | |
printf("{ Querybuffer length:%d, m.offset: %d}\n",map_buffer.length,map_buffer.m.offset); | |
void *map_address = mmap(NULL, \ | |
map_buffer.length, \ | |
PROT_READ | PROT_WRITE ,\ | |
MAP_SHARED, \ | |
camera_fd, map_buffer.m.offset); | |
if(map_address == MAP_FAILED){ | |
printf("mmap failed!\n"); | |
exit(1); | |
} | |
struct v4l2_buffer camera_buf; | |
camera_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
camera_buf.memory = V4L2_MEMORY_MMAP; | |
camera_buf.index = 0; | |
if(-1 == ioctl(camera_fd, VIDIOC_QBUF, &camera_buf)) | |
{ | |
perror("VIDIOC_QBUF"); | |
exit(EXIT_FAILURE); | |
} | |
enum v4l2_buf_type type; | |
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
if(-1 == ioctl(camera_fd,VIDIOC_STREAMON,&type)) | |
{ | |
perror("VIDIOC_STREAMON"); | |
exit(EXIT_FAILURE); | |
} | |
fd_set fds; | |
struct timeval tv; | |
int camera_index; | |
char *filename = malloc(20*sizeof(char)); | |
for(camera_index = 0;camera_index < MAX_FPS;camera_index++) | |
{ | |
FD_ZERO(&fds); | |
FD_SET(camera_fd, &fds); | |
tv.tv_sec = 2; | |
tv.tv_usec = 0; | |
ret = select(camera_fd+1,&fds,NULL,NULL,&tv); | |
if(ret == -1) | |
{ | |
perror("select"); | |
exit(EXIT_FAILURE); | |
} | |
if(ret == 0) | |
{ | |
fprintf(stderr,"select time out\n"); | |
exit(EXIT_FAILURE); | |
} | |
struct v4l2_buffer get_buffer; | |
get_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
get_buffer.memory = V4L2_MEMORY_MMAP; | |
if(-1 == ioctl(camera_fd,VIDIOC_DQBUF,&get_buffer)) | |
{ | |
perror("VIDIOC_DQBUF"); | |
exit(EXIT_FAILURE); | |
} | |
printf("{ Get Buffer OK index:%d length: %d time: %ld:%ld}\n",get_buffer.index,get_buffer.length,get_buffer.timestamp.tv_sec,get_buffer.timestamp.tv_usec); | |
unsigned char *rgb_buffer = malloc(640*480*3*sizeof(unsigned char)); | |
convert_yuv_to_rgb_buffer(map_address,rgb_buffer,640,480); | |
sprintf(filename,"./camera-%d.jpg",camera_index); | |
//************************************* | |
//MJPG | |
// | |
/*FILE * file;*/ | |
/*if((file = fopen(filename,"wb")) == NULL){*/ | |
/*printf("open file failed\n");*/ | |
/*exit(EXIT_FAILURE);*/ | |
/*}*/ | |
/*fwrite(map_address,get_buffer.length,1,file);*/ | |
/*fclose(file);*/ | |
//************************************* | |
//YUYV2jpg | |
// | |
FILE *out; | |
out = fopen(filename,"wb"); | |
create_jpeg(rgb_buffer,filename); | |
fclose(out); | |
free(rgb_buffer); | |
if(screen_display(filename) == -1) | |
printf("Display screen failed!\n"); | |
//yuv422_to_jpeg(rgb_buffer,640,480,out,80); | |
if(-1 == ioctl(camera_fd,VIDIOC_QBUF,&get_buffer)) | |
{ | |
perror("VIDIOC_QBUF"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
if(-1 == munmap(map_address,map_buffer.length)) | |
{ | |
perror("munmap"); | |
exit(EXIT_FAILURE); | |
} | |
printf("munmap,then exit\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment