您的位置:首页 > 运维架构 > Linux

明天回家啦,庆祝一下,贡献一段源码,基于linux V4L视频采集摄像程序

2006-07-10 15:21 561 查看
/*****************************************************************************************************

linux_m4v.c

gcc -o linux_m4v linux_m4v.c -lc -lm -lxvidcore

*******************************************************************************************************/

#include <string.h>
#include <sys/types.h>

#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>

#include "xvid_encode.h"
void *enc_handle = NULL;

int done = 0;
int
enc_main(unsigned char *image,
unsigned char *bitstream,
int *key,
int *stats_type,
int *stats_quant,
int *stats_length,
int sse[3]);
int
enc_stop();
int

enc_init(int use_assembler);
double
msecond();

#define VIDEO_PALETTE_JPEG 21

struct vdIn {
int fd;
char *videodevice ;
struct video_capability videocap;
struct video_picture videopict;
struct video_window videowin;
int framesizeIn ;
int bppIn;
int hdrwidth;
int hdrheight;
int formatIn;
};

struct vdIn videoIn;
int init_videoIn (struct vdIn *vd, char *device, int width, int height,int format);
static int GetDepth (int format);
static int GetVideoPict (struct vdIn *vd);
static int SetVideoPict (struct vdIn *vd);

int main(int argc,char *argv[])
{
char *device;

int format = VIDEO_PALETTE_YUV420P;
int width = 352;
int height = 288;
int i;
unsigned char r_buffer[304128];
unsigned char* mp4_buffer;

double enctime;
double totalenctime = 0.;
float totalPSNR[3] = {0., 0., 0.};
device = "/dev/video0";
ARG_OUTPUTFILE = "test.m4v";
int use_assembler = 1;
int result;
int totalsize;
int m4v_size;
int key;
int stats_type;
int stats_quant;
int stats_length;
int input_num;
int output_num;

char filename[256];
FILE *out_file = NULL;

memset (&videoIn, 0, sizeof (struct vdIn));
if (init_videoIn(&videoIn, device, width, height,format) != 0)
printf (" damned encore rate !!/n");
/* xvid init */
ARG_SAVEMPEGSTREAM = 1;
ARG_SAVEINDIVIDUAL = 0;

XDIM = width;
YDIM = height;
mp4_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM, YDIM) * 2);

totalsize = 0;

result = 0;
result = enc_init(0);
if (result != 0) {
fprintf(stderr, "Encore INIT problem, return value %d/n",result);
goto release_all;
}

/* i=read(videoIn.fd,r_buffer,304128);
printf("i read : %d/n",i);
if(i<0){
printf("error read!/n");
close(videoIn.fd);
return -1;
}
*/
input_num = 0; /* input frame counter */
output_num = 0;

if (ARG_SAVEMPEGSTREAM && ARG_OUTPUTFILE) {

if ((out_file = fopen(ARG_OUTPUTFILE, "w+b")) == NULL) {
fprintf(stderr, "Error opening output file %s/n", ARG_OUTPUTFILE);
goto release_all;
}

} else {
out_file = NULL;
}

/* Xvid encode */
do {

char *type;
int sse[3];
i=read(videoIn.fd,r_buffer,304128);
printf("i read : %d/n",i);
if(i<0){
printf("error read!/n");
close(videoIn.fd);
return -1;
}

if (input_num >= ARG_MAXFRAMENR) {
//result = 1;
done = 1;
}
enctime = msecond();
m4v_size =enc_main(!result ? (unsigned char*)r_buffer:0,mp4_buffer, &key, &stats_type,&stats_quant, &stats_length, sse);
enctime = msecond() - enctime;
printf("m4v_size is %d /n",m4v_size);
if (m4v_size < 0) {
printf("erro in encode..../n");
}

/* Update encoding time stats */
totalenctime += enctime;
totalsize += m4v_size;
if (m4v_size > 0 && ARG_SAVEMPEGSTREAM) {

/* Save single files */
if (ARG_SAVEINDIVIDUAL) {
FILE *out;
sprintf(filename, "%sframe%05d.m4v", filepath, output_num);
out = fopen(filename, "w+b");
fwrite(mp4_buffer, m4v_size, 1, out);
fclose(out);
output_num++;
}
/* Save ES stream */
if (ARG_OUTPUTFILE && out_file)
fwrite(mp4_buffer, 1, m4v_size, out_file);
}

input_num++;

} while (!done);

if(m4v_size<0){
printf("error write_jpeg!/n");
close(videoIn.fd);
fclose(out_file);
return -1;
}
printf("OK./n");

release_all:

if (enc_handle) {
result = enc_stop();
if (result)
fprintf(stderr, "Encore RELEASE problem return value %d/n",
result);
}

fclose(out_file);
close(videoIn.fd);
return 0;
}

int init_videoIn (struct vdIn *vd, char *device, int width, int height,
int format)
{
int erreur;
vd->hdrwidth = width;
vd->hdrheight = height;
vd->formatIn = format;
vd->bppIn = GetDepth (vd->formatIn);

if ((vd->fd = open (device, O_RDWR)) == -1){
printf("ERROR opening V4L interface/n");
close(vd->fd);
return -1;
}
if (ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap)) == -1){
printf("ERROR opening video_capability interface/n");
close(vd->fd);
return -1;
}
printf ("Camera found: %s /n", vd->videocap.name);

erreur = GetVideoPict (vd);
vd->videopict.palette = vd->formatIn;
vd->videopict.depth = GetDepth (vd->formatIn);
vd->bppIn = GetDepth (vd->formatIn);

vd->framesizeIn = (vd->hdrwidth * vd->hdrheight * vd->bppIn) >> 3;

erreur = SetVideoPict (vd);
erreur = GetVideoPict (vd);
if (vd->formatIn != vd->videopict.palette ||
vd->bppIn != vd->videopict.depth){
printf("ERROR set video_picture interface/n");
close(vd->fd);
return -1;
}
if (erreur < 0){
printf("ERROR set palette /n");
close(vd->fd);
return -1;
}
if (ioctl (vd->fd, VIDIOCGWIN, &(vd->videowin)) < 0)
perror ("VIDIOCGWIN failed /n");
vd->videowin.height = vd->hdrheight;
vd->videowin.width = vd->hdrwidth;
if (ioctl (vd->fd, VIDIOCSWIN, &(vd->videowin)) < 0)
perror ("VIDIOCSWIN failed /n");
if (ioctl (vd->fd, VIDIOCGWIN, &(vd->videowin)) < 0)
perror ("VIDIOCGWIN failed /n");
printf ("VIDIOCSWIN height %d width %d /n",
vd->videowin.height, vd->videowin.width);
return 0;
}

static int
GetDepth (int format)
{
int depth;
switch (format)
{

case VIDEO_PALETTE_JPEG:
{
depth = 8;
}
break;
case VIDEO_PALETTE_RAW:
{
depth = 8;
}
break;
case VIDEO_PALETTE_YUV420P:
{
//depth = (8 * 3) >> 1;
depth = 24;
}
break;
case VIDEO_PALETTE_RGB565:
depth = 16;
break;
case VIDEO_PALETTE_RGB24:
depth = 24;
break;
case VIDEO_PALETTE_RGB32:
{
depth = 32;
}
break;
default:
depth = -1;
break;
}
return depth;
}

static int
GetVideoPict (struct vdIn *vd)
{
if (ioctl (vd->fd, VIDIOCGPICT, &vd->videopict) < 0){
printf("ERROR opening video_capability interface/n");
close(vd->fd);
return -1;
}

printf ("VIDIOCGPICT brightnes=%d hue=%d color=%d contrast=%d whiteness=%d"
"depth=%d palette=%d/n", vd->videopict.brightness,
vd->videopict.hue, vd->videopict.colour, vd->videopict.contrast,
vd->videopict.whiteness, vd->videopict.depth,
vd->videopict.palette);

return 0;
}

static int
SetVideoPict (struct vdIn *vd)
{
if (ioctl (vd->fd, VIDIOCSPICT, &vd->videopict) < 0){
printf("ERROR set video_capability interface/n");
close(vd->fd);
return -1;
}

printf ("VIDIOCSPICT brightnes=%d hue=%d color=%d contrast=%d whiteness=%d"
"depth=%d palette=%d/n", vd->videopict.brightness,
vd->videopict.hue, vd->videopict.colour, vd->videopict.contrast,
vd->videopict.whiteness, vd->videopict.depth,
vd->videopict.palette);

return 0;
}

double
msecond()
{

struct timeval tv;

gettimeofday(&tv, 0);
return (tv.tv_sec * 1.0e3 + tv.tv_usec * 1.0e-3);

}

#define FRAMERATE_INCR 1001

int

enc_init(int use_assembler)

{

int xerr;

//xvid_plugin_cbr_t cbr;

xvid_plugin_single_t single;

xvid_plugin_2pass1_t rc2pass1;

xvid_plugin_2pass2_t rc2pass2;

//xvid_plugin_fixed_t rcfixed;

xvid_enc_plugin_t plugins[7];

xvid_gbl_init_t xvid_gbl_init;

xvid_enc_create_t xvid_enc_create;

/*------------------------------------------------------------------------

* XviD core initialization

*----------------------------------------------------------------------*/

/* Set version -- version checking will done by xvidcore */

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

xvid_gbl_init.version = XVID_VERSION;

xvid_gbl_init.debug = 0;

/* Do we have to enable ASM optimizations ? */

if (use_assembler) {

xvid_gbl_init.cpu_flags = 0;

}

/* Initialize XviD core -- Should be done once per __process__ */

xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);

/*------------------------------------------------------------------------

* XviD encoder initialization

*----------------------------------------------------------------------*/

/* Version again */

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

xvid_enc_create.version = XVID_VERSION;

/* Width and Height of input frames */

xvid_enc_create.width = XDIM;

xvid_enc_create.height = YDIM;

xvid_enc_create.profile = XVID_PROFILE_S_L3;

/* init plugins */

xvid_enc_create.zones = NULL;

xvid_enc_create.num_zones = 0;

xvid_enc_create.plugins = NULL;

xvid_enc_create.num_plugins = 0;

/* No fancy thread tests */

xvid_enc_create.num_threads = 0;

/* Frame rate - Do some quick float fps = fincr/fbase hack */

if ((ARG_FRAMERATE - (int) ARG_FRAMERATE) < SMALL_EPS) {

xvid_enc_create.fincr = 1;

xvid_enc_create.fbase = (int) ARG_FRAMERATE;

} else {

xvid_enc_create.fincr = FRAMERATE_INCR;

xvid_enc_create.fbase = (int) (FRAMERATE_INCR * ARG_FRAMERATE);

}

/* Maximum key frame interval */

if (ARG_MAXKEYINTERVAL > 0) {

xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;

}else {

xvid_enc_create.max_key_interval = (int) ARG_FRAMERATE *10;

}

/* Bframes settings */

xvid_enc_create.max_bframes = 0;

xvid_enc_create.bquant_ratio = 150;

xvid_enc_create.bquant_offset = 100;

/* Dropping ratio frame -- we don't need that */

xvid_enc_create.frame_drop_ratio = 0;

/* Global encoder options */

xvid_enc_create.global = 0;

/* I use a small value here, since will not encode whole movies, but short clips */

xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);

/* Retrieve the encoder instance from the structure */

enc_handle = xvid_enc_create.handle;

return (xerr);

}

int
enc_stop()
{
int xerr;

/* Destroy the encoder instance */
xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);

return (xerr);
}

int
enc_main(unsigned char *image,
unsigned char *bitstream,
int *key,
int *stats_type,
int *stats_quant,
int *stats_length,
int sse[3])
{
int ret;

xvid_enc_frame_t xvid_enc_frame;
xvid_enc_stats_t xvid_enc_stats;

/* Version for the frame and the stats */
memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
xvid_enc_frame.version = XVID_VERSION;

memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
xvid_enc_stats.version = XVID_VERSION;

/* Bind output buffer */
xvid_enc_frame.bitstream = bitstream;
xvid_enc_frame.length = -1;

/* Initialize input image fields */
if (image) {
xvid_enc_frame.input.plane[0] = image;
#ifndef READ_PNM
if (ARG_INPUTTYPE==2)
xvid_enc_frame.input.csp = XVID_CSP_YV12;
else
xvid_enc_frame.input.csp = XVID_CSP_I420;
xvid_enc_frame.input.stride[0] = XDIM;
#else
xvid_enc_frame.input.csp = XVID_CSP_BGR;
xvid_enc_frame.input.stride[0] = XDIM*3;
#endif
} else {
xvid_enc_frame.input.csp = XVID_CSP_NULL;
}

/* Set up core's general features */
xvid_enc_frame.vol_flags = 0;
if (ARG_STATS)
xvid_enc_frame.vol_flags |= XVID_VOL_EXTRASTATS;
if (ARG_QTYPE)
xvid_enc_frame.vol_flags |= XVID_VOL_MPEGQUANT;
if (ARG_QPEL)
xvid_enc_frame.vol_flags |= XVID_VOL_QUARTERPEL;
if (ARG_GMC)
xvid_enc_frame.vol_flags |= XVID_VOL_GMC;
if (ARG_INTERLACING)
xvid_enc_frame.vol_flags |= XVID_VOL_INTERLACING;

/* Set up core's general features */
xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY];

if (ARG_VOPDEBUG) {
xvid_enc_frame.vop_flags |= XVID_VOP_DEBUG;
}

if (ARG_GREYSCALE) {
xvid_enc_frame.vop_flags |= XVID_VOP_GREYSCALE;
}

/* Frame type -- let core decide for us */
xvid_enc_frame.type = XVID_TYPE_AUTO;

/* Force the right quantizer -- It is internally managed by RC plugins */
xvid_enc_frame.quant = 0;

/* Set up motion estimation flags */
xvid_enc_frame.motion = motion_presets[ARG_QUALITY];

if (ARG_GMC)
xvid_enc_frame.motion |= XVID_ME_GME_REFINE;

if (ARG_QPEL)
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16;
if (ARG_QPEL && (xvid_enc_frame.vop_flags & XVID_VOP_INTER4V))
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8;

if (ARG_TURBO)
xvid_enc_frame.motion |= XVID_ME_FASTREFINE16 | XVID_ME_FASTREFINE8 |
XVID_ME_SKIP_DELTASEARCH | XVID_ME_FAST_MODEINTERPOLATE |
XVID_ME_BFRAME_EARLYSTOP;

if (ARG_BVHQ)
xvid_enc_frame.vop_flags |= XVID_VOP_RD_BVOP;

switch (ARG_VHQMODE) /* this is the same code as for vfw */
{
case 1: /* VHQ_MODE_DECISION */
xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
break;

case 2: /* VHQ_LIMITED_SEARCH */
xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
break;

case 3: /* VHQ_MEDIUM_SEARCH */
xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
break;

case 4: /* VHQ_WIDE_SEARCH */
xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
xvid_enc_frame.motion |= XVID_ME_EXTSEARCH_RD;
break;

default :
break;
}

if (ARG_QMATRIX) {
/* We don't use special matrices */
xvid_enc_frame.quant_intra_matrix = qmatrix_intra;
xvid_enc_frame.quant_inter_matrix = qmatrix_inter;
}
else {
/* We don't use special matrices */
xvid_enc_frame.quant_intra_matrix = NULL;
xvid_enc_frame.quant_inter_matrix = NULL;
}

/* Encode the frame */
ret = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,
&xvid_enc_stats);

*key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);
*stats_type = xvid_enc_stats.type;
*stats_quant = xvid_enc_stats.quant;
*stats_length = xvid_enc_stats.length;
sse[0] = xvid_enc_stats.sse_y;
sse[1] = xvid_enc_stats.sse_u;
sse[2] = xvid_enc_stats.sse_v;

return (ret);
}

/********************************xvid_encode.h**********************************/

#ifndef XVID_ENCODE_H
#define XVID_ENCODE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <sys/time.h>

#include "xvid.h"

#define ABS_MAXFRAMENR 9999

static const int motion_presets[] = {
/* quality 0 */
0,

/* quality 1 */
XVID_ME_ADVANCEDDIAMOND16,

/* quality 2 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16,

/* quality 3 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8,

/* quality 4 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,

/* quality 5 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,

/* quality 6 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,

};
#define ME_ELEMENTS (sizeof(motion_presets)/sizeof(motion_presets[0]))

static const int vop_presets[] = {
/* quality 0 */
0,

/* quality 1 */
0,

/* quality 2 */
XVID_VOP_HALFPEL,

/* quality 3 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V,

/* quality 4 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V,

/* quality 5 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
XVID_VOP_TRELLISQUANT,

/* quality 6 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED,

};
#define VOP_ELEMENTS (sizeof(vop_presets)/sizeof(vop_presets[0]))

static int ARG_STATS = 0;
static int ARG_DUMP = 0;
static int ARG_LUMIMASKING = 0;
static int ARG_BITRATE = 0;
static int ARG_SINGLE = 0;
static char *ARG_PASS1 = 0;
static char *ARG_PASS2 = 0;
static int ARG_QUALITY = ME_ELEMENTS - 1;
static float ARG_FRAMERATE = 25.00f;
static int ARG_MAXFRAMENR = ABS_MAXFRAMENR;
static int ARG_MAXKEYINTERVAL = 0;
static char *ARG_INPUTFILE = NULL;
static int ARG_INPUTTYPE = 0;
static int ARG_SAVEMPEGSTREAM = 0;
static int ARG_SAVEINDIVIDUAL = 0;
static char *ARG_OUTPUTFILE = NULL;
static int XDIM = 0;
static int YDIM = 0;
static int ARG_BQRATIO = 150;
static int ARG_BQOFFSET = 100;
static int ARG_MAXBFRAMES = 0;
static int ARG_PACKED = 0;
static int ARG_DEBUG = 0;
static int ARG_VOPDEBUG = 0;
static int ARG_GREYSCALE = 0;
static int ARG_QTYPE = 0;
static int ARG_QMATRIX = 0;
static int ARG_GMC = 0;
static int ARG_INTERLACING = 0;
static int ARG_QPEL = 0;
static int ARG_TURBO = 0;
static int ARG_VHQMODE = 0;
static int ARG_BVHQ = 0;
static int ARG_CLOSED_GOP = 0;

#define MAX_ZONES 64

static xvid_enc_zone_t ZONES[MAX_ZONES];
static int NUM_ZONES = 0;

#define SMALL_EPS (1e-10)
#define FRAMERATE_INCR 1001

static unsigned char qmatrix_intra[64];
static unsigned char qmatrix_inter[64];

static char filepath[256] = "./";

#define IMAGE_SIZE(x,y) ((x)*(y)*3/2)

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: