DOC

linux_dvb_dvr

By Rachel Dunn,2014-12-13 21:35
5 views 0
linux_dvb_dvrlinux,dvb,dvr,DVR,LINUX,Linux,DVB

    这是一个简单的;但却是相当完整的DVRsource codeLINUX MPEG4 DVR源代码。此中只有视频;没有音频;落鹤生推荐大家好好看看。此代码可用以下命令编译?gcc -o linux_dvr linux_dvr.c -lxvidcore。有问题可以来论坛(http://bbs.rosoo.net)讨论。 #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));

Report this document

For any questions or suggestions please email
cust-service@docsford.com