Linux MPEG4 DVR源代码


Linux MPEG4 DVR源代码,还包括一个可以跨平台运行的MPEG4 播放器(需要XVID与SDL开发库包)

一.Linux DVR源码

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <stdint.h>   
  4. #include <errno.h>   
  5. #include <fcntl.h>   
  6. #include <signal.h>   
  7. #include <sys/ioctl.h>   
  8. #include <sys/mman.h>   
  9. #include <linux/videodev.h>   
  10. #include "xvid.h"   
  11. #define FRAMERATE_INCR 1001   
  12. #define SMALL_EPS (1e-10)   
  13. #define VIDEO "/dev/video"   
  14. #define INDEX 0   
  15. #define IOCTL(fd, req, addr ) \   
  16. ((-1==ioctl(fd,req,addr))?(perror(#req),close(fd),exit(EXIT_FAILURE)):0)   
  17.   
  18. static float ARG_FRAMERATE = 25.00f;   
  19. static int ARG_QUALITY = 4;   
  20. static int ARG_MAXKEYINTERVAL = 250;   
  21. static char * ARG_OUTPUTFILE= "out.m4u";   
  22. static FILE * fp = NULL;   
  23. static int done = 0;   
  24. static const int motion_presets[] = {   
  25.     /* quality 0 */  
  26.     0,   
  27.   
  28.     /* quality 1 */  
  29.     XVID_ME_ADVANCEDDIAMOND16,   
  30.   
  31.     /* quality 2 */  
  32.     XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16,   
  33.   
  34.     /* quality 3 */  
  35.     XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |   
  36.     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8,   
  37.   
  38.     /* quality 4 */  
  39.     XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |   
  40.     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |   
  41.     XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,   
  42.   
  43.     /* quality 5 */  
  44.     XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |   
  45.     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |   
  46.     XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,   
  47.   
  48.     /* quality 6 */  
  49.     XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |   
  50.     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |   
  51.     XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,   
  52.   
  53. };   
  54. static const int vop_presets[] = {   
  55.     /* quality 0 */  
  56.     0,   
  57.   
  58.     /* quality 1 */  
  59.     0,   
  60.   
  61.     /* quality 2 */  
  62.     XVID_VOP_HALFPEL,   
  63.   
  64.     /* quality 3 */  
  65.     XVID_VOP_HALFPEL | XVID_VOP_INTER4V,   
  66.   
  67.     /* quality 4 */  
  68.     XVID_VOP_HALFPEL | XVID_VOP_INTER4V,   
  69.   
  70.     /* quality 5 */  
  71.     XVID_VOP_HALFPEL | XVID_VOP_INTER4V |   
  72.     XVID_VOP_TRELLISQUANT,   
  73.   
  74.     /* quality 6 */  
  75.     XVID_VOP_HALFPEL | XVID_VOP_INTER4V |   
  76.     XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED,   
  77.   
  78. };   
  79.   
  80. static int XDIM=352,YDIM=288;   
  81. static use_assembler = 0;   
  82. static void *enc_handle = NULL;   
  83.   
  84. static int enc_init(int use_assembler);   
  85. static int enc_main(unsigned char *image,   
  86.                     unsigned char *bitstream,   
  87.                     int *key,   
  88.                     int *stats_type,   
  89.                     int *stats_quant,   
  90.                     int *stats_length,   
  91.                     int stats[3]);   
  92. static int enc_stop();   
  93. //signal act method defination   
  94. static void clean(int signum)   
  95. {   
  96.     done=1;   
  97. }   
  98. int    
  99. main(int argc,char *argv[])   
  100. {   
  101.     //register SIGINT action method ,to save the m4u file   
  102.     signal(SIGINT,clean);   
  103.     int fd;   
  104.     struct v4l2_capability cap;       
  105.     struct v4l2_format format;   
  106.     struct v4l2_requestbuffers reqbuf;   
  107.     struct v4l2_buffer buffer;   
  108.     struct v4l2_input input;   
  109.     int index=0,i;   
  110.     for (i=1; i< argc; i++) {   
  111.     
  112.         if (strcmp("-asm", argv[i]) == 0 ) {   
  113.             use_assembler = 1;   
  114.         }else if(strcmp("-f", argv[i]) == 0 && i < argc -1){   
  115.             i++;   
  116.             ARG_OUTPUTFILE = argv[i];   
  117.         }else if(strcmp("-i", argv[i]) == 0 && i < argc -1){   
  118.             i++;   
  119.             index = atoi(argv[i]);   
  120.         } else if(strcmp("-w", argv[i]) == 0 && i < argc -1){   
  121.             i++;   
  122.             XDIM = atoi(argv[i]);   
  123.         } else if(strcmp("-h", argv[i]) == 0 && i < argc -1){   
  124.             i++;   
  125.             YDIM = atoi(argv[i]);   
  126.         }    
  127.     }   
  128.        
  129.     //init capture card   
  130.        
  131.     fd = open(VIDEO,O_RDWR);   
  132.     if(fd<0)   
  133.     {   
  134.         perror("Can't open /dev/video device");   
  135.         exit(errno);   
  136.     }   
  137.     //if card can't support video capture and by means of steamio,exit    
  138.        
  139.     IOCTL(fd, VIDIOC_QUERYCAP, &cap);   
  140.     if ( !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)   
  141.          &&!(cap.capabilities & V4L2_CAP_STREAMING))   
  142.     {   
  143.         fprintf(stderr, "Couldn't use the card \n");   
  144.         exit(3);   
  145.     }          
  146.        
  147.     //query input and select the desired input   
  148.        
  149.     IOCTL(fd, VIDIOC_G_INPUT, &index);   
  150.     input.index = index;   
  151.     IOCTL(fd, VIDIOC_ENUMINPUT, &input);   
  152.     printf ("Current input: Index %i,Name %s\n", index,input.name);       
  153.     for(i=0;;i++)   
  154.     {   
  155.         if(i!=index)   
  156.         {   
  157.             input.index = i;   
  158.             if(-1==ioctl(fd, VIDIOC_ENUMINPUT, &input))   
  159.                 break;   
  160.             else  
  161.                 printf ("Other input: Index %i,Name %s\n",i,input.name);   
  162.         }   
  163.     }   
  164.     IOCTL(fd, VIDIOC_S_INPUT, &index);   
  165.        
  166.     //get current video format,set the desired format   
  167.        
  168.     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
  169.     IOCTL(fd,VIDIOC_G_FMT,&format);   
  170.     format.fmt.pix.width = XDIM;   
  171.     format.fmt.pix.height = YDIM;   
  172.     format.fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;   
  173.     format.fmt.pix.field = V4L2_FIELD_ANY;//V4L2_FIELD_INTERLACED   
  174.        
  175.     IOCTL(fd,VIDIOC_S_FMT,&format);   
  176.   
  177.     XDIM = format.fmt.pix.width;   
  178.     printf("Gotten width %d\n",XDIM);   
  179.     YDIM = format.fmt.pix.height;   
  180.     printf("Gotten height %d\n",YDIM);   
  181.        
  182.     //let driver get the buffers   
  183.        
  184.     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
  185.     reqbuf.memory = V4L2_MEMORY_MMAP;   
  186.     reqbuf.count = 4;   
  187.     IOCTL(fd,VIDIOC_REQBUFS,&reqbuf );   
  188.     if (reqbuf.count < 4)    
  189.     {   
  190.        printf ("Not enough buffer memory for driver\n");   
  191.        exit (5);   
  192.     }   
  193.   
  194. //mmap the driver's buffer to application address   
  195.        
  196.     //create relative buffers struct to be used by mmap   
  197.   
  198.     struct    
  199.     {   
  200.         void * start;   
  201.         size_t length;   
  202.     } buffers[reqbuf.count];   
  203.        
  204.     //mmap the driver's kernel buffer into application   
  205.        
  206.     for (i=0;i<reqbuf.count;i++)   
  207.     {   
  208.         buffer.type = reqbuf.type;   
  209.         buffer.index =i ;   
  210.            
  211.         //query the status of one buffer ,mmap the driver buffer   
  212.            
  213.         IOCTL(fd,VIDIOC_QUERYBUF,&buffer);   
  214.         buffers[i].length = buffer.length;   
  215.         buffers[i].start = mmap (NULL,buffer.length,   
  216.                                  PROT_READ | PROT_WRITE,   
  217.                                  MAP_SHARED,   
  218.                                  fd,buffer.m.offset);   
  219.         if (buffers[i].start == MAP_FAILED)    
  220.         {   
  221.            close(fd);   
  222.            perror ("mmap");   
  223.            exit(errno);   
  224.         }   
  225.     }   
  226.     //begin video capture   
  227.        
  228.     IOCTL(fd,VIDIOC_STREAMON,&reqbuf.type);            
  229.        
  230.     //enqueue all driver buffers   
  231.     for (i=0;i<reqbuf.count;i++)   
  232.     {           
  233.         buffer.type = reqbuf.type;   
  234.         buffer.index = i;   
  235.         IOCTL(fd,VIDIOC_QUERYBUF, &buffer);   
  236.         IOCTL(fd,VIDIOC_QBUF,&buffer);   
  237.     }    
  238.     //init xvid   
  239.        
  240.     int result;   
  241.     result = enc_init(1);   
  242.     if(result!=0)   
  243.     {   
  244.     fprintf(stderr, "Encore INIT problem, return value %d\n", result);   
  245.     goto clean_all;              
  246.     }   
  247.        
  248.     //get mem of mpg4 frame   
  249.        
  250.     uint8_t *mp4_buffer = NULL;       
  251.     mp4_buffer = (unsigned char *) malloc(XDIM*YDIM);   
  252.     if (mp4_buffer==NULL)   
  253.     {   
  254.         fprintf(stderr,"malloc error");   
  255.         goto clean_all;   
  256.     }   
  257.     int key;   
  258.     int stats_type;   
  259.     int stats_quant;   
  260.     int stats_length;   
  261.     int sse[3];        
  262.        
  263.     //create store mp4 file   
  264.        
  265.     fp= fopen(ARG_OUTPUTFILE, "rb");   
  266.     if (fp== NULL) {   
  267.         perror("Error opening output file.");   
  268.         exit(-1);   
  269.     }          
  270.   
  271. //main loop ,frame capture,compressed    
  272.   
  273.     i = 0;   
  274.     int outbytes,m4v_size;   
  275.     while(!done)   
  276.     {   
  277.         //dequeue one frame   
  278.                
  279.         buffer.type = reqbuf.type;   
  280.         buffer.index = i;   
  281.         IOCTL(fd, VIDIOC_QUERYBUF, &buffer);   
  282.         IOCTL(fd, VIDIOC_DQBUF, &buffer);   
  283.         /*debug info  
  284.         printf("current frame's unix time seconds :%d\n",buffer.timestamp.tv_sec);  
  285.         printf("current frame's unix time mcicoseconds :%d\n",buffer.timestamp.tv_usec);  
  286.         */  
  287.           
  288.         //compress a frame   
  289.            
  290.         m4v_size = enc_main((uint8_t *)buffers[i].start,   
  291.                              mp4_buffer+16,   
  292.                              &key, &stats_type,&stats_quant, &stats_length, sse);   
  293.            
  294.         //store into output file   
  295.         outbytes = fwrite(mp4_buffer, 1, m4v_size, fp);   
  296.         if(outbytes != m4v_size)   
  297.         {   
  298.             fprintf(stderr,"Error writing the m4u file\n");   
  299.             exit(7);   
  300.         }   
  301.            
  302.         //enqueue one frame   
  303.                
  304.         buffer.type = reqbuf.type;   
  305.         buffer.index = i;   
  306.         IOCTL(fd, VIDIOC_QUERYBUF, &buffer );   
  307.         IOCTL(fd, VIDIOC_QBUF, &buffer );   
  308.         i++;               
  309.         if( i >= reqbuf.count )    
  310.             i = 0;   
  311.     }   
  312. clean_all:   
  313.     fclose(fp);   
  314.     enc_stop();       
  315.     //stop capture   
  316.     IOCTL(fd, VIDIOC_STREAMOFF, &reqbuf.type );   
  317.     //unmmap the apllication buffer   
  318.     for (i=0;i<reqbuf.count;i++)   
  319.         munmap (buffers[i].start,buffers[i].length);       
  320.     //release the dynamic mem   
  321.     close(fd);   
  322.     return 0;   
  323. }   
  324.   
  325. int  
  326. enc_init(int use_assembler)   
  327. {   
  328.     int xerr;   
  329.     //xvid_plugin_cbr_t cbr;   
  330.     xvid_plugin_single_t single;   
  331.     xvid_plugin_2pass1_t rc2pass1;   
  332.     xvid_plugin_2pass2_t rc2pass2;   
  333.     //xvid_plugin_fixed_t rcfixed;   
  334.     xvid_enc_plugin_t plugins[7];   
  335.     xvid_gbl_init_t xvid_gbl_init;   
  336.     xvid_enc_create_t xvid_enc_create;   
  337.   
  338.     /*------------------------------------------------------------------------  
  339.      * XviD core initialization  
  340.      *----------------------------------------------------------------------*/  
  341.   
  342.     /* Set version -- version checking will done by xvidcore */  
  343.     memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));   
  344.     xvid_gbl_init.version = XVID_VERSION;   
  345.     xvid_gbl_init.debug = 0;   
  346.   
  347.   
  348.     /* Do we have to enable ASM optimizations ? */  
  349.     if (use_assembler) {   
  350.         xvid_gbl_init.cpu_flags = 0;   
  351.     }   
  352.   
  353.     /* Initialize XviD core -- Should be done once per __process__ */  
  354.     xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);   
  355.   
  356.     /*------------------------------------------------------------------------  
  357.      * XviD encoder initialization  
  358.      *----------------------------------------------------------------------*/  
  359.   
  360.     /* Version again */  
  361.     memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));   
  362.     xvid_enc_create.version = XVID_VERSION;   
  363.   
  364.     /* Width and Height of input frames */  
  365.     xvid_enc_create.width = XDIM;   
  366.     xvid_enc_create.height = YDIM;   
  367.     xvid_enc_create.profile = XVID_PROFILE_S_L3;   
  368.   
  369.     /* init plugins  */  
  370.     xvid_enc_create.zones = NULL;   
  371.     xvid_enc_create.num_zones = 0;   
  372.   
  373.     xvid_enc_create.plugins = NULL;   
  374.     xvid_enc_create.num_plugins = 0;   
  375.   
  376.     /* No fancy thread tests */  
  377.     xvid_enc_create.num_threads = 0;   
  378.   
  379.     /* Frame rate - Do some quick float fps = fincr/fbase hack */  
  380.     if ((ARG_FRAMERATE - (int) ARG_FRAMERATE) < SMALL_EPS) {   
  381.         xvid_enc_create.fincr = 1;   
  382.         xvid_enc_create.fbase = (int) ARG_FRAMERATE;   
  383.     } else {   
  384.         xvid_enc_create.fincr = FRAMERATE_INCR;   
  385.         xvid_enc_create.fbase = (int) (FRAMERATE_INCR * ARG_FRAMERATE);   
  386.     }   
  387.   
  388.     /* Maximum key frame interval */  
  389.     if (ARG_MAXKEYINTERVAL > 0) {   
  390.         xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;   
  391.     }else {   
  392.         xvid_enc_create.max_key_interval = (int) ARG_FRAMERATE *10;   
  393.     }   
  394.   
  395.     /* Bframes settings */  
  396.     xvid_enc_create.max_bframes = 0;   
  397.     xvid_enc_create.bquant_ratio = 150;   
  398.     xvid_enc_create.bquant_offset = 100;   
  399.   
  400.     /* Dropping ratio frame -- we don't need that */  
  401.     xvid_enc_create.frame_drop_ratio = 0;   
  402.   
  403.     /* Global encoder options */  
  404.     xvid_enc_create.global = 0;   
  405.   
  406.     /* I use a small value here, since will not encode whole movies, but short clips */  
  407.     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);   
  408.   
  409.     /* Retrieve the encoder instance from the structure */  
  410.     enc_handle = xvid_enc_create.handle;   
  411.   
  412.     return (xerr);   
  413. }   
  414.   
  415. int  
  416. enc_main(unsigned char *image,   
  417.          unsigned char *bitstream,   
  418.          int *key,   
  419.          int *stats_type,   
  420.          int *stats_quant,   
  421.          int *stats_length,   
  422.          int sse[3])   
  423. {   
  424.     int ret;   
  425.   
  426.     xvid_enc_frame_t xvid_enc_frame;   
  427.     xvid_enc_stats_t xvid_enc_stats;   
  428.   
  429.     /* Version for the frame and the stats */  
  430.     memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));   
  431.     xvid_enc_frame.version = XVID_VERSION;   
  432.   
  433.     memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));   
  434.     xvid_enc_stats.version = XVID_VERSION;   
  435.   
  436.     /* Bind output buffer */  
  437.     xvid_enc_frame.bitstream = bitstream;   
  438.     xvid_enc_frame.length = -1;   
  439.   
  440.     /* Initialize input image fields */  
  441.     if (image) {   
  442.         xvid_enc_frame.input.plane[0] = image;   
  443.         xvid_enc_frame.input.csp = XVID_CSP_I420;   
  444.         xvid_enc_frame.input.stride[0] = XDIM;   
  445.     } else {   
  446.         xvid_enc_frame.input.csp = XVID_CSP_NULL;   
  447.     }   
  448.   
  449.     /* Set up core's general features */  
  450.     xvid_enc_frame.vol_flags = 0;   
  451.   
  452.     /* Set up core's general features */  
  453.     xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY];   
  454.   
  455.     /* Frame type -- let core decide for us */  
  456.     xvid_enc_frame.type = XVID_TYPE_AUTO;   
  457.   
  458.     /* Force the right quantizer -- It is internally managed by RC plugins */  
  459.     xvid_enc_frame.quant = 3;   
  460.   
  461.     /* Set up motion estimation flags */  
  462.     xvid_enc_frame.motion = motion_presets[ARG_QUALITY];   
  463.   
  464.     /* We don't use special matrices */  
  465.     xvid_enc_frame.quant_intra_matrix = NULL;   
  466.     xvid_enc_frame.quant_inter_matrix = NULL;   
  467.   
  468.     /* Encode the frame */  
  469.     ret = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,   
  470.                       &xvid_enc_stats);   
  471.   
  472.     *key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);   
  473.     *stats_type = xvid_enc_stats.type;   
  474.     *stats_quant = xvid_enc_stats.quant;   
  475.     *stats_length = xvid_enc_stats.length;   
  476.     sse[0] = xvid_enc_stats.sse_y;   
  477.     sse[1] = xvid_enc_stats.sse_u;   
  478.     sse[2] = xvid_enc_stats.sse_v;   
  479.     return (ret);   
  480. }   
  481.   
  482. int  
  483. enc_stop()   
  484. {   
  485.     int xerr;   
  486.   
  487.     /* Destroy the encoder instance */  
  488.     xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);   
  489.   
  490.     return (xerr);   
  491. }  
  • 1
  • 2
  • 下一页

相关内容