#include <pthread.h>
#include <asm/types.h> /* for videodev2.h */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <sys/time.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <linux/videodev2.h>
#include <dirent.h>
#include "video_capture.h"
#include "h264encoder.h"
typedef enum{
FRAME_INVALID=0,
FRAME_VALID,
}frame_state_t;
typedef struct _raw_frame{
pthread_mutex_t lock;
pthread_cond_t cond;
uint8_t * buf;
frame_state_t state;
struct _raw_frame* next;
}raw_frame_t;
typedef struct {
}raw_frame_queue_t;
#define MAX_FRAME_BUF_SIZE 10
#define FRAME_SIZE (640*480*2)
#define BUF_SIZE (FRAME_SIZE*10)
raw_frame_t * raw_frame_read_head;
raw_frame_t * raw_frame_write_head;
raw_frame_t raw_frame_buf[MAX_FRAME_BUF_SIZE];
unsigned char encodebuf[FRAME_SIZE];
#define CLEAR(x) memset (&(x), 0, sizeof (x))
typedef unsigned char uint8_t;
static char *dev_name = "/dev/video0";
char h264_file_name[100] = "zgy.h264\0";
FILE *h264_fp;
uint8_t *h264_buf;
char yuv_file_name[100] = "zgy_640x480.yuv\0";
FILE *yuv_fp;
unsigned int n_buffers = 0;
DIR *dirp;
Encoder en;
int cnt = 0;
unsigned char *framebuf=0;
void InitFrameQueue(void)
{
int i;
raw_frame_t* p;
framebuf = malloc(BUF_SIZE);
for(i=0;i<MAX_FRAME_BUF_SIZE;i++)
{
p=&raw_frame_buf[i];
p->buf=framebuf+i*FRAME_SIZE;
pthread_mutex_init(&p->lock,NULL);
pthread_cond_init(&p->cond,NULL);
p->state = FRAME_INVALID;
if(i==0)
{
raw_frame_write_head=raw_frame_read_head = p;
p->next = &raw_frame_buf[i+1];
}
else if(i>=(MAX_FRAME_BUF_SIZE-1))
{
p->next = &raw_frame_buf[0];//�����
}
else
p->next = &raw_frame_buf[i+1];
}
}
void FreeFrameQueue(void)
{
int i;
raw_frame_t* p;
for(i=0;i<MAX_FRAME_BUF_SIZE;i++)
{
p=&raw_frame_buf[i];
pthread_mutex_destroy(&p->lock);
pthread_cond_destroy(&p->cond);
p->buf=NULL;
p->next=NULL;
}
free(framebuf);
framebuf=NULL;
}
void PutFrameQueue(unsigned char* buf,int len)
{
static int putcnt=0;
raw_frame_t* ptmp=raw_frame_write_head;
if(ptmp)
{
pthread_mutex_lock(&ptmp->lock);
if(ptmp->state==FRAME_INVALID)
{
memcpy(ptmp->buf,buf,FRAME_SIZE);
ptmp->state=FRAME_VALID;
pthread_cond_signal(&ptmp->cond);
raw_frame_write_head=raw_frame_write_head->next;
printf("put =%d\n",putcnt++);
}
pthread_mutex_unlock(&ptmp->lock);
}
}
int GetFrameQueue(unsigned char*buf)
{
static int getcnt=0;
int len =0;
raw_frame_t* ptmp=raw_frame_read_head;
if(ptmp)
{
pthread_mutex_lock(&ptmp->lock);
if(ptmp->state==FRAME_INVALID)
{
extern int encodethreadexit;
if(encodethreadexit)
{
printf("encode thread exit\n");
pthread_mutex_unlock(&ptmp->lock);
exit(0);
}
pthread_cond_wait(&ptmp->cond,&ptmp->lock);
}
memcpy(buf,ptmp->buf,FRAME_SIZE);
ptmp->state=FRAME_INVALID;
raw_frame_read_head=raw_frame_read_head->next;
pthread_mutex_unlock(&ptmp->lock);
len = FRAME_SIZE;
printf("get =%d\n",getcnt++);
}
return len;
}
int CheckFrameQueueEmty(void)
{
int ret=0;
raw_frame_t* ptmp=raw_frame_read_head;
if(ptmp)
{
pthread_mutex_lock(&ptmp->lock);
if(ptmp->state==FRAME_INVALID)
{
ret =1;
}
pthread_mutex_unlock(&ptmp->lock);
}
return ret;
}
void errno_exit(const char *s) {
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
int xioctl(int fd, int request, void *arg) {
int r = 0;
do {
r = ioctl(fd, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
void open_camera(struct camera *cam) {
struct stat st;
if (-1 == stat(cam->device_name, &st)) {
fprintf(stderr, "Cannot identify '%s': %d, %s\n", cam->device_name,
errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (!S_ISCHR(st.st_mode)) {
fprintf(stderr, "%s is no device\n", cam->device_name);
exit(EXIT_FAILURE);
}
cam->fd = open(cam->device_name, O_RDWR, 0); // | O_NONBLOCK
if (-1 == cam->fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n", cam->device_name, errno,
strerror(errno));
exit(EXIT_FAILURE);
}
}
void close_camera(struct camera *cam) {
if (-1 == close(cam->fd))
errno_exit("close");
cam->fd = -1;
}
void init_file() {
h264_fp = fopen(h264_file_name, "wa+");
yuv_fp = fopen(yuv_file_name, "wa+");
}
void close_file() {
fclose(h264_fp);
fclose(yuv_fp);
}
void init_encoder(struct camera *cam) {
compress_begin(&en, cam->width, cam->height);
h264_buf = (uint8_t *) malloc(
sizeof(uint8_t) * cam->width * cam->height * 3); // 设置缓冲区
}
void close_encoder() {
compress_end(&en);
free(h264_buf);
}
void encode_frame(uint8_t *yuv_frame, size_t yuv_length) {
int h264_length = 0;
//这里有一个问题,通过测试发现前6帧都是0,所以这里我跳过了为0的帧
if (yuv_frame[0] == '\0')
return;
#if 0
h264_length = compress_frame(&en, -1, yuv_frame, h264_buf);
if (h264_length > 0) {
//写h264文件
fwrite(h264_buf, h264_length, 1, h264_fp);
}
#endif
//写yuv文件
fwrite(yuv_frame, yuv_length, 1, yuv_fp);
}
void encode_frame_NEW(void)
{
int len;
len=GetFrameQueue(encodebuf);
if(len)
fwrite(encodebuf, len, 1, yuv_fp);
}
int read_and_encode_frame(struct camera *cam) {
struct v4l2_buffer buf;
printf("in read_frame\n");
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//this operator below will change buf.index and (0 <= buf.index <= 3)
if (-1 == xioctl(cam->fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("VIDIOC_DQBUF");
}
}
//encode_frame(cam->buffers[buf.index].start, buf.length);
PutFrameQueue(cam->buffers[buf.index].start,buf.length);
if (-1 == xioctl(cam->fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
return 1;
}
void start_capturing(struct camera *cam) {
unsigned int i;
enum v4l2_buf_type type;
for (i = 0; i < n_buffers; ++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(cam->fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(cam->fd, VIDIOC_STREAMON, &type))
errno_exit("VIDIOC_STREAMON");
}
void stop_capturing(struct camera *cam) {
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(cam->fd, VIDIOC_STREAMOFF, &type))
errno_exit("VIDIOC_STREAMOFF");
}
void uninit_camera(struct camera *cam) {
unsigned int i;
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap(cam->buffers[i].start, cam->buffers[i].length))
errno_exit("munmap");
free(cam->buffers);
}
void init_mmap(struct camera *cam) {
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
//分配内存
if (-1 == xioctl(cam->fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf(stderr, "%s does not support "
"memory mapping\n", cam->device_name);
exit(EXIT_FAILURE);
} else {
errno_exit("VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
fprintf(stderr, "Insufficient buffer memory on %s\n", cam->device_name);
exit(EXIT_FAILURE);
}
cam->buffers = calloc(req.count, sizeof(*(cam->buffers)));
if (!cam->buffers) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
//将VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
if (-1 == xioctl(cam->fd, VIDIOC_QUERYBUF, &buf))
errno_exit("VIDIOC_QUERYBUF");
cam->buffers[n_buffers].length = b
LINUX下采集V4L2摄像头数据源码
3星 · 超过75%的资源 需积分: 45 143 浏览量
2016-11-06
20:30:10
上传
评论 7
收藏 1.93MB ZIP 举报
ywa037
- 粉丝: 7
- 资源: 11
最新资源
- J185-VB一款SOT23封装P-Channel场效应MOS管
- 计算整数各位数字之和,利用java代码实现
- J185-T2B-VB一款SOT23封装P-Channel场效应MOS管
- map20231226Kalmanfilter.ipynb
- J185-T1B-VB一款SOT23封装P-Channel场效应MOS管
- ASME Y14.5-2018 尺寸与公差标注 中文版
- J185-T1B-A-VB一款SOT23封装P-Channel场效应MOS管
- J168-VB一款SOT23封装P-Channel场效应MOS管
- J166-VB一款SOT23封装P-Channel场效应MOS管
- i2c测试程序-linux-如何调试i2c.pdf
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈