Linux MPEG4 DVR源代码

#include <stdio.h>    #include <stdlib.h>    #include <stdint.h>    #include <errno.h>    #include <fcntl.h>    #include <signal.h>    #include <sys/ioctl.h>    #include <sys/mman.h>    #include <linux/videodev.h>    #include "xvid.h"    #define FRAMERATE_INCR 1001    #define SMALL_EPS (1e-10)    #define VIDEO "/dev/video"    #define INDEX 0    #define IOCTL(fd, req, addr ) \    ((-1==ioctl(fd,req,addr))?(perror(#req),close(fd),exit(EXIT_FAILURE)):0)       static float ARG_FRAMERATE = 25.00f;    static int ARG_QUALITY = 4;    static int ARG_MAXKEYINTERVAL = 250;    static char * ARG_OUTPUTFILE= "out.m4u";    static FILE * fp = NULL;    static int done = 0;    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,       };    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,       };       static int XDIM=352,YDIM=288;    static use_assembler = 0;    static void *enc_handle = NULL;       static int enc_init(int use_assembler);    static int enc_main(unsigned char *image,                        unsigned char *bitstream,                        int *key,                        int *stats_type,                        int *stats_quant,                        int *stats_length,                        int stats[3]);    static int enc_stop();    //signal act method defination    static void clean(int signum)    {        done=1;    }    int     main(int argc,char *argv[])    {        //register SIGINT action method ,to save the m4u file        signal(SIGINT,clean);        int fd;        struct v4l2_capability cap;            struct v4l2_format format;        struct v4l2_requestbuffers reqbuf;        struct v4l2_buffer buffer;        struct v4l2_input input;        int index=0,i;        for (i=1; i< argc; i++) {                 if (strcmp("-asm", argv[i]) == 0 ) {                use_assembler = 1;            }else if(strcmp("-f", argv[i]) == 0 && i < argc -1){                i++;                ARG_OUTPUTFILE = argv[i];            }else if(strcmp("-i", argv[i]) == 0 && i < argc -1){                i++;                index = atoi(argv[i]);            } else if(strcmp("-w", argv[i]) == 0 && i < argc -1){                i++;                XDIM = atoi(argv[i]);            } else if(strcmp("-h", argv[i]) == 0 && i < argc -1){                i++;                YDIM = atoi(argv[i]);            }         }                //init capture card                fd = open(VIDEO,O_RDWR);        if(fd<0)        {            perror("Can't open /dev/video device");            exit(errno);        }        //if card can't support video capture and by means of steamio,exit                 IOCTL(fd, VIDIOC_QUERYCAP, &cap);        if ( !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)             &&!(cap.capabilities & V4L2_CAP_STREAMING))        {            fprintf(stderr, "Couldn't use the card \n");            exit(3);        }                       //query input and select the desired input                IOCTL(fd, VIDIOC_G_INPUT, &index);        input.index = index;        IOCTL(fd, VIDIOC_ENUMINPUT, &input);        printf ("Current input: Index %i,Name %s\n", index,input.name);            for(i=0;;i++)        {            if(i!=index)            {                input.index = i;                if(-1==ioctl(fd, VIDIOC_ENUMINPUT, &input))                    break;                else                   printf ("Other input: Index %i,Name %s\n",i,input.name);            }        }        IOCTL(fd, VIDIOC_S_INPUT, &index);                //get current video format,set the desired format                format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        IOCTL(fd,VIDIOC_G_FMT,&format);        format.fmt.pix.width = XDIM;        format.fmt.pix.height = YDIM;        format.fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;        format.fmt.pix.field = V4L2_FIELD_ANY;//V4L2_FIELD_INTERLACED                IOCTL(fd,VIDIOC_S_FMT,&format);           XDIM = format.fmt.pix.width;        printf("Gotten width %d\n",XDIM);        YDIM = format.fmt.pix.height;        printf("Gotten height %d\n",YDIM);                //let driver get the buffers                reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        reqbuf.memory = V4L2_MEMORY_MMAP;        reqbuf.count = 4;        IOCTL(fd,VIDIOC_REQBUFS,&reqbuf );        if (reqbuf.count < 4)         {           printf ("Not enough buffer memory for driver\n");           exit (5);        }       //mmap the driver's buffer to application address                //create relative buffers struct to be used by mmap           struct         {            void * start;            size_t length;        } buffers[reqbuf.count];                //mmap the driver's kernel buffer into application                for (i=0;i<reqbuf.count;i++)        {            buffer.type = reqbuf.type;            buffer.index =i ;                        //query the status of one buffer ,mmap the driver buffer                        IOCTL(fd,VIDIOC_QUERYBUF,&buffer);            buffers[i].length = buffer.length;            buffers[i].start = mmap (NULL,buffer.length,                                     PROT_READ | PROT_WRITE,                                     MAP_SHARED,                                     fd,buffer.m.offset);            if (buffers[i].start == MAP_FAILED)             {               close(fd);               perror ("mmap");               exit(errno);            }        }        //begin video capture                IOCTL(fd,VIDIOC_STREAMON,&reqbuf.type);                         //enqueue all driver buffers        for (i=0;i<reqbuf.count;i++)        {                    buffer.type = reqbuf.type;            buffer.index = i;            IOCTL(fd,VIDIOC_QUERYBUF, &buffer);            IOCTL(fd,VIDIOC_QBUF,&buffer);        }         //init xvid                int result;        result = enc_init(1);        if(result!=0)        {        fprintf(stderr, "Encore INIT problem, return value %d\n", result);        goto clean_all;                   }                //get mem of mpg4 frame                uint8_t *mp4_buffer = NULL;            mp4_buffer = (unsigned char *) malloc(XDIM*YDIM);        if (mp4_buffer==NULL)        {            fprintf(stderr,"malloc error");            goto clean_all;        }        int key;        int stats_type;        int stats_quant;        int stats_length;        int sse[3];                     //create store mp4 file                fp= fopen(ARG_OUTPUTFILE, "rb");        if (fp== NULL) {            perror("Error opening output file.");            exit(-1);        }              //main loop ,frame capture,compressed            i = 0;        int outbytes,m4v_size;        while(!done)        {            //dequeue one frame                            buffer.type = reqbuf.type;            buffer.index = i;            IOCTL(fd, VIDIOC_QUERYBUF, &buffer);            IOCTL(fd, VIDIOC_DQBUF, &buffer);            /*debug info           printf("current frame's unix time seconds :%d\n",buffer.timestamp.tv_sec);           printf("current frame's unix time mcicoseconds :%d\n",buffer.timestamp.tv_usec);           */                      //compress a frame                        m4v_size = enc_main((uint8_t *)buffers[i].start,                                 mp4_buffer+16,                                 &key, &stats_type,&stats_quant, &stats_length, sse);                        //store into output file            outbytes = fwrite(mp4_buffer, 1, m4v_size, fp);            if(outbytes != m4v_size)            {                fprintf(stderr,"Error writing the m4u file\n");                exit(7);            }                        //enqueue one frame                            buffer.type = reqbuf.type;            buffer.index = i;            IOCTL(fd, VIDIOC_QUERYBUF, &buffer );            IOCTL(fd, VIDIOC_QBUF, &buffer );            i++;                        if( i >= reqbuf.count )                 i = 0;        }    clean_all:        fclose(fp);        enc_stop();            //stop capture        IOCTL(fd, VIDIOC_STREAMOFF, &reqbuf.type );        //unmmap the apllication buffer        for (i=0;i<reqbuf.count;i++)            munmap (buffers[i].start,buffers[i].length);            //release the dynamic mem        close(fd);        return 0;    }       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_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;            xvid_enc_frame.input.csp = XVID_CSP_I420;            xvid_enc_frame.input.stride[0] = XDIM;        } else {            xvid_enc_frame.input.csp = XVID_CSP_NULL;        }           /* Set up core's general features */       xvid_enc_frame.vol_flags = 0;           /* Set up core's general features */       xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY];           /* 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 = 3;           /* Set up motion estimation flags */       xvid_enc_frame.motion = motion_presets[ARG_QUALITY];           /* 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);    }       int   enc_stop()    {        int xerr;           /* Destroy the encoder instance */       xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);           return (xerr);    }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxyxf.html