📄 main.c
字号:
/*
* Description :
* This is a V4L capture program and send video frames to streaming
* server.
*
* Authors : Jen-Yu Yu <babyfish@vstream.com.tw>
* Copyright (C) 2006
* Industrial Technology Research Institute (http://www.itri.org.tw)
*/
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <linux/videodev.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <linux/fb.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/un.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include "fmpeg4_avcodec.h"
#include "fmjpeg_avcodec.h"
#include "ratecontrol.h"
#include "motiondet.h"
#include "../FConfig/config_access.h"
#define FMPEG4_ENCODER_DEV "/dev/fenc"
#define NEW_VERSION
#define JPEG_STORE_NUM 1
#define WORK_FRAMERATE 2
//For high resolution 1280x1024
//#define MAX_WIDTH_1280
#define DEV0
FILE *dout;
#ifdef DEV0
#define devicename "/dev/video0"
#define dout_name "/mnt/nfs/dev0.m4v"
#else
#define devicename "/dev/video1"
#define dout_name "/mnt/nfs/dev1.m4v"
#endif
int fmpeg4_get_intra_quant_tbls(unsigned char *intra_qtbl);
int fmpeg4_get_inter_quant_tbls(unsigned char *inter_qtbl);
int enc_close(video_profile *avctx);
void init_time( int framerate );
struct frame_info{
int vop_time_increment_resolution;
int vop_time_increment;
int vtir_bitlen;
};
typedef struct fcap_frame_buff
{
unsigned int phyAddr;
unsigned int mmapAddr; //length per dma buffer
unsigned int frame_no;
}fcap_frame_buff_t;
void send_to_server(int ctlfd, uint8_t* frame_buf, int len);
int connect_to_server(void);
//void msg_loop();
//static struct timeb tv_init, tv_last;
int time_init = 0;
int longterm_frame_count = 0;
static int insert_frame = 0;
//static struct frame_info frameinfo;
struct mcfg mval;
int video_running;
int devfd = -1;
int jpg_num = 1;
int initial_bitrate = 0;
int max_bitrate, auto_bandwidth;
int fmpeg4_enc_fd = 0;
RateControl ratec;
int ctlfd;
video_profile video_setting;
int video_fd = -1;
struct video_mbuf gb_buffers;
struct video_mmap gb_buf;
unsigned char *video_buf_virt;
int mmap_done = 0;
unsigned char *out_virt_buffer;
unsigned int frame_count = 0,V_bitrate = 0;
struct video_capability video_cap;
struct video_window win;
struct video_tuner tuner;
unsigned int frm_count=0;
int cap_width,cap_height;
static int fFrameRate=30;
extern int stop_encode;
//pthread_t time_thread;
static int ingrab=-1;
unsigned char cust_intra_qtbl[64],cust_inter_qtbl[64];
//sem_t bin_sem;
//for motion dection
MACROBLOCK_INFO *mdinfo=0;
#ifdef NEW_VERSION
//unsigned char * mmap_addr;
int frame_num = 0;
#endif
int v4l_init(void)
{
video_fd = open(devicename, O_RDWR);
if(video_fd < 0)
{
printf("open device failure");
return -1;
}
#ifndef NEW_VERSION
if (ioctl(video_fd, VIDIOCGCAP, &video_cap) < 0) /// query video capture capability
{
printf("VIDIOCGCAP failure");
return -1;
}
if (!(video_cap.type & VID_TYPE_CAPTURE))
{
printf("Fatal: grab device does not handle capture\n");
return -1;
}
#endif
if (!ioctl(video_fd, VIDIOCGTUNER, &tuner))
{
tuner.mode = VIDEO_MODE_NTSC;
ioctl(video_fd, VIDIOCSTUNER, &tuner);
}
return 0;
}
/* This function only work when IPTV station */
void iptv_setting(int ingrab)
{
/* Fix to set audio path for IPTV station */
switch (ingrab)
{
case 9: //svideo
system("tv -t 2");
break;
case 10: //tuner
system("tv -t 8");
system("tv -a 4 -m 2");
system("tv -d 4 -c 50");
break;
case 11: //composite
system("tv -t 1");
break;
}
}
int mp4_init(struct video_profile profile)
{
// int i;
cap_width = profile.width;
cap_height = profile.height;
#ifndef NEW_VERSION
win.x = 0;
win.y = 0;
win.width = cap_width;
win.height = cap_height;
win.chromakey = -1;
win.flags = 0;
if (ioctl(video_fd, VIDIOCSWIN, &win)< 0) {
printf ("set window error\n");
return -1;
}
#endif
if ( ioctl(video_fd,VIDIOCGMBUF,&gb_buffers) < 0 )
{
printf("capture not support mbuf\n");
return -1;
}
if (0 == mmap_done) {
mmap_done = 1;
#ifndef NEW_VERSION
for(i=0; i<gb_buffers.frames; i++){
gb_buffers.offsets[i] = mmap(0, gb_buffers.size, PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, 0);
if ((unsigned char*)-1 == gb_buffers.offsets[i])
{
printf("mmap error\n");
return -1;
}
}
#else
video_buf_virt = mmap(0, gb_buffers.size, PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, 0);
//printf("gb_buffers.size=%d\n", gb_buffers.size);
#endif
ioctl(video_fd, 0x5679, &ingrab); //grab type
ioctl(video_fd, 0x5678, 0);
iptv_setting(ingrab);
}
gb_buf.height = cap_height;
gb_buf.width = cap_width;
gb_buf.format = VIDEO_PALETTE_YUV420P;
/*first trigger*/
gb_buf.frame = 0;
frame_count=0;
return 0;
}
typedef struct {
const char *abv;
int width, height;
int frame_rate, frame_rate_base;
} AbvEntry;
static AbvEntry frame_abvs[] = {
{ "ntsc", 720, 480, 30000, 1001 },
{ "pal", 720, 576, 25, 1 },
{ "qntsc", 352, 240, 30000, 1001 }, /* VCD compliant ntsc */
{ "qpal", 352, 288, 25, 1 }, /* VCD compliant pal */
{ "sntsc", 640, 480, 30000, 1001 }, /* square pixel ntsc */
{ "spal", 768, 576, 25, 1 }, /* square pixel pal */
{ "film", 352, 240, 24, 1 },
{ "ntsc-film", 352, 240, 24000, 1001 },
{ "sqcif", 128, 96, 0, 0 },
{ "qcif", 176, 144, 0, 0 },
{ "cif", 352, 288, 0, 0 },
{ "4cif", 704, 576, 0, 0 },
};
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
{
int i;
int n = sizeof(frame_abvs) / sizeof(AbvEntry);
const char *p;
int frame_width = 0, frame_height = 0;
for(i=0;i<n;i++) {
if (!strcmp(frame_abvs[i].abv, str)) {
frame_width = frame_abvs[i].width;
frame_height = frame_abvs[i].height;
break;
}
}
if (i == n) {
p = str;
frame_width = strtol(p, (char **)&p, 10);
if (*p)
p++;
frame_height = strtol(p, (char **)&p, 10);
}
if (frame_width <= 0 || frame_height <= 0)
return -1;
*width_ptr = frame_width;
*height_ptr = frame_height;
return 0;
}
static void get_arg(char *buf, int buf_size, const char **pp)
{
const char *p;
char *q;
int quote;
p = *pp;
while (isspace(*p)) p++;
q = buf;
quote = 0;
if (*p == '\"' || *p == '\'')
quote = *p++;
for(;;) {
if (quote) {
if (*p == quote)
break;
} else {
if (isspace(*p))
break;
}
if (*p == '\0')
break;
if ((q - buf) < buf_size - 1)
*q++ = *p;
p++;
}
*q = '\0';
if (quote && *p == quote)
p++;
*pp = p;
}
static int read_video_config(const char *filename, struct video_profile* profile)
{
FILE *f;
char line[1024];
char cmd[64];
char arg[1024];
const char *p;
int line_num;
f = fopen(filename, "r");
if (!f) {
perror(filename);
return -1;
}
line_num = 0;
for(;;) {
if (fgets(line, sizeof(line), f) == NULL)
break;
line_num++;
p = line;
while (isspace(*p))
p++;
if (*p == '\0' || *p == '#')
continue;
get_arg(cmd, sizeof(cmd), &p);
if (!strcasecmp(cmd, "VideoCodec")) {
get_arg(arg, sizeof(arg), &p);
}
else if (!strcasecmp(cmd, "VideoFrameRate")) {
get_arg(arg, sizeof(arg), &p);
profile->framerate = atoi(arg);
profile->frame_rate_base = 1;
}
else if (!strcasecmp(cmd, "VideoInput")) {
get_arg(arg, sizeof(arg), &p);
ingrab=atoi(arg);
}
else if (!strcasecmp(cmd, "VideoSize")) {
get_arg(arg, sizeof(arg), &p);
parse_image_size(&profile->width, &profile->height, arg);
}
else if (!strcasecmp(cmd, "VideoBitRate")) {
get_arg(arg, sizeof(arg), &p);
profile->bit_rate = atoi(arg);
}
else if (!strcasecmp(cmd, "VideoGopSize")) {
get_arg(arg, sizeof(arg), &p);
profile->gop_size = atoi(arg);
}
else if (!strcasecmp(cmd, "VideoQuant")) {
get_arg(arg, sizeof(arg), &p);
profile->quant = atoi(arg);
profile->qmin = profile->quant;
profile->qmax = profile->quant;
}
else if (!strcasecmp(cmd, "QMax")) {
get_arg(arg, sizeof(arg), &p);
profile->qmax = atoi(arg);
}
else if (!strcasecmp(cmd, "QMin")) {
get_arg(arg, sizeof(arg), &p);
profile->qmin = atoi(arg);
}
else if (!strcasecmp(cmd, "4MV")) {
get_arg(arg, sizeof(arg), &p);
profile->enable_4mv = atoi(arg);
}
}
fclose(f);
return 0;
}
void motion_info_set(MOTION_INFO *motion)
{
motion->range_mb_x0_LU = mval.x0_LU;
motion->range_mb_y0_LU = mval.y0_LU;
motion->range_mb_x0_RD = mval.x0_RD;
motion->range_mb_y0_RD = mval.y0_RD;
motion->range_mb_x1_LU = mval.x1_LU;
motion->range_mb_y1_LU = mval.y1_LU;
motion->range_mb_x1_RD = mval.x1_RD;
motion->range_mb_y1_RD = mval.y1_RD;
motion->range_mb_x2_LU = mval.x2_LU;
motion->range_mb_y2_LU = mval.y2_LU;
motion->range_mb_x2_RD = mval.x2_RD;
motion->range_mb_y2_RD = mval.y2_RD;
motion->MV_th0 = mval.mv_th0;
motion->sad_th0 = mval.sad_th0;
motion->delta_dev_th0 = mval.dev_th0;
motion->MV_th1 = mval.mv_th1;
motion->sad_th1 = mval.sad_th1;
motion->delta_dev_th1 = mval.dev_th1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -