*******************************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #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 #include #include #include #include #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