• c 摄像头利用v4l2直接生成avi视频(不利用ffmpeg)


    自定义avi结构头文件。现在不能实时显示摄像头画面,准备参照fim(终端中显示图片),直接对显示framebuffer操作,显示视频。不用qt等。

    生成的视频根据机子的性能不同,诂计要手动调一下生成视频的帧率

    播放: $ aplay  musicdemo.wmv

    录音: $ arecord -c 2 -r 44100 -f S16_LE musicdemo.wmv

    调节音量大小: $ alsamixer 

    deepin安装 alsa-lib

    sudo apt-get install libasound2-dev   

    main.c

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/stat.h>
    4. #include <fcntl.h>
    5. #include <stdlib.h>
    6. #include <unistd.h>
    7. #include <sys/ioctl.h>
    8. #include <linux/videodev2.h>
    9. #include <string.h>
    10. #include <sys/mman.h>
    11. #include "Avi.h"
    12. int main(void){
    13. int fd = open("/dev/video0", O_RDWR);
    14. if(fd < 0)
    15. {
    16. perror("打开设备失败");
    17. return -1;
    18. }
    19. struct v4l2_format vfmt;
    20. vfmt.type=1;
    21. vfmt.fmt.pix.width=1680;
    22. vfmt.fmt.pix.height=1080;
    23. vfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG;
    24. int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
    25. if(ret < 0)
    26. {
    27. perror("设置格式失败");
    28. }
    29. struct v4l2_requestbuffers reqbuffer;
    30. reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    31. reqbuffer.count = 1;
    32. reqbuffer.memory = V4L2_MEMORY_MMAP ;
    33. ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
    34. if(ret < 0)
    35. {
    36. perror("申请队列空间失败");
    37. }
    38. struct v4l2_buffer mapbuffer;
    39. unsigned char *mptr;
    40. unsigned int size;
    41. mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    42. mapbuffer.index = 0;
    43. ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
    44. if(ret < 0)
    45. {
    46. perror("查询内核空间队列失败");
    47. }
    48. int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    49. ret = ioctl(fd, VIDIOC_STREAMON, &type); //启动流
    50. if(ret < 0)
    51. {
    52. perror("开启失败");
    53. }
    54. mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE,
    55. MAP_SHARED, fd,0); //设备映射到缓冲区内存
    56. size=mapbuffer.length;
    57. ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区数据放入读队列中
    58. if(ret < 0)
    59. {
    60. perror("放回失败");
    61. }
    62. //---------------------------------------------------------------------------
    63. FILE *file=avi_ks();
    64. while(nframes<100){
    65. ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer); //读当前队列缓冲区的数据
    66. if(ret < 0)
    67. {
    68. perror("提取数据失败");
    69. }
    70. int size=1280*720;
    71. unsigned char tmp[4] = {'0', '0', 'd', 'c'}; //00dc = 压缩的视频数据
    72. fwrite(tmp, 4, 1, file); //写入是否是压缩的视频数据信息
    73. fwrite(&size, 4, 1, file); //写入4字节对齐后的JPEG图像大小
    74. fwrite(mptr,size, 1, file); //写入真正的JPEG数据
    75. ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区数据放入读队列中
    76. if(ret < 0)
    77. {
    78. perror("放回失败");
    79. }
    80. nframes++;
    81. totalsize++;
    82. }
    83. //---------------------------------------------------------
    84. ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
    85. avi_end(file);
    86. munmap(mptr, size);
    87. close(fd);
    88. return 0;
    89. }

    avi.c

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <malloc.h>
    6. #include <wait.h>
    7. #include <sys/types.h>
    8. #include <sys/stat.h>
    9. #include <fcntl.h>
    10. #include <sys/ioctl.h>
    11. #include <sys/mman.h>
    12. #include "Avi.h"
    13. FILE * avi_ks(void){
    14. FILE *fp= fopen("sample.avi","wb");
    15. fseek(fp,sizeof(HEAD),SEEK_SET);
    16. return fp;
    17. }
    18. //--------------------------------------------------------
    19. int avi_add(FILE*fp,char *data,int size){
    20. unsigned char tmp[4] = {'0', '0', 'd', 'c'}; //00dc = 压缩的视频数据
    21. fwrite(tmp, 4, 1, fp); //写入是否是压缩的视频数据信息
    22. fwrite(&size, 4, 1, fp); //写入4字节对齐后的JPEG图像大小
    23. fwrite(data,size, 1, fp); //写入真正的JPEG数据
    24. return 0;
    25. }
    26. //----------------------------------------------------------------------------------
    27. int avi_end(FILE *f_file){
    28. int width=1280;
    29. int height=720;
    30. typedef struct hdrl AVI_HDRL_LIST;
    31. typedef struct movi AVI_LIST_HEAD;
    32. typedef struct avih AVI_AVIH_CHUNK;
    33. typedef struct strl AVI_STRL_LIST;
    34. typedef struct strh AVI_STRH_CHUNK;
    35. typedef struct strf AVI_STRF_CHUNK;
    36. typedef struct avi AVI_HEAD;
    37. AVI_HEAD avi_head={
    38. {
    39. {'R', 'I', 'F', 'F'},
    40. 4 + sizeof(AVI_HDRL_LIST) + sizeof(AVI_LIST_HEAD) +nframes * 8 + totalsize,
    41. {'A', 'V', 'I', ' '}
    42. },
    43. {
    44. {'L', 'I', 'S', 'T'},
    45. sizeof(AVI_HDRL_LIST) - 8,
    46. {'h', 'd', 'r', 'l'},
    47. {
    48. {'a', 'v', 'i', 'h'},
    49. sizeof(AVI_AVIH_CHUNK) - 8,
    50. 1000000, 25000, 0, 0,nframes, 0, 1, 1000000, width, height,
    51. {0, 0, 0, 0}
    52. },
    53. {
    54. {'L', 'I', 'S', 'T'},
    55. sizeof(AVI_STRL_LIST) - 8,
    56. {'s', 't', 'r', 'l'},
    57. {
    58. {'s', 't', 'r', 'h'},
    59. sizeof(AVI_STRH_CHUNK) - 8,
    60. {'v', 'i', 'd', 's'},
    61. {'J', 'P', 'E', 'G'},
    62. 0, 0, 0, 0, 1, 15, 0, nframes, 100000, 0xFFFFFF, 0,
    63. {0, 0, width, height}
    64. },
    65. {
    66. {'s', 't', 'r', 'f'},
    67. sizeof(AVI_STRF_CHUNK) - 8,
    68. sizeof(AVI_STRF_CHUNK) - 8,
    69. width, height, 1, 24,
    70. {'J', 'P', 'E', 'G'},
    71. width * height * 3, 0, 0, 0, 0
    72. }
    73. }
    74. },
    75. {
    76. {'L', 'I', 'S', 'T'},
    77. 4 + nframes * 8 + totalsize,
    78. {'m', 'o', 'v', 'i'}
    79. }
    80. };
    81. fseek(f_file, 0, SEEK_SET);
    82. fwrite(&avi_head,sizeof(HEAD),1,f_file);
    83. fclose(f_file);
    84. printf("end\n");
    85. }

    avi.h

    1. #ifndef AVI_H
    2. #define AVI_H
    3. #include <stdio.h>
    4. static int nframes; //总帧数
    5. static int totalsize;
    6. FILE * avi_ks(void);
    7. int avi_add(FILE*fp,char *data,int size);
    8. int avi_end(FILE *f_file);
    9. struct avi{
    10. struct riff{
    11. unsigned char id[4];
    12. unsigned int size;
    13. unsigned char type[4];
    14. }r1;
    15. struct hdrl{
    16. unsigned char id[4]; //块ID,固定为LIST
    17. unsigned int size; //块大小,等于struct avi_hdrl_list去掉id和size的大小
    18. unsigned char type[4]; //块类型,固定为hdrl
    19. struct avih{
    20. unsigned char id[4]; //块ID,固定为avih
    21. unsigned int size; //块大小,等于struct avi_avih_chunk去掉id和size的大小
    22. unsigned int us_per_frame; //视频帧间隔时间(以微秒为单位)
    23. unsigned int max_bytes_per_sec; //AVI文件的最大数据率
    24. unsigned int padding; //设为0即可
    25. unsigned int flags; //AVI文件全局属性,如是否含有索引块、音视频数据是否交叉存储等
    26. unsigned int total_frames; //总帧数
    27. unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
    28. unsigned int streams; //文件包含的流的个数,仅有视频流时为1
    29. unsigned int suggest_buff_size; //指定读取本文件建议使用的缓冲区大小,通常为存储一桢图像 //以及同步声音所需的数据之和,不指定时设为0
    30. unsigned int width; //视频主窗口宽度(单位:像素)
    31. unsigned int height; //视频主窗口高度(单位:像素)
    32. unsigned int reserved[4]; //保留段,设为0即可
    33. }a1;
    34. struct strl{
    35. unsigned char id[4]; //块ID,固定为LIST
    36. unsigned int size; //块大小,等于struct avi_strl_list去掉id和size的大小
    37. unsigned char type[4]; //块类型,固定为strl
    38. struct strh{
    39. unsigned char id[4]; //块ID,固定为strh
    40. unsigned int size; //块大小,等于struct avi_strh_chunk去掉id和size的大小
    41. unsigned char stream_type[4]; //流的类型,vids表示视频流,auds表示音频流
    42. unsigned char codec[4]; //指定处理这个流需要的解码器,如JPEG
    43. unsigned int flags; //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
    44. unsigned short priority; //流的优先级,视频流设为0即可
    45. unsigned short language; //音频语言代号,视频流设为0即可
    46. unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
    47. unsigned int scale; //
    48. unsigned int rate; //对于视频流,rate / scale = 帧率fps
    49. unsigned int start; //对于视频流,设为0即可
    50. unsigned int length; //对于视频流,length即总帧数
    51. unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
    52. unsigned int quality; //流数据的质量指标
    53. unsigned int sample_size; //音频采样大小,视频流设为0即可
    54. struct rcFrame{ //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
    55. short left;
    56. short top;
    57. short right;
    58. short bottom;
    59. } AVI_RECT_FRAME;
    60. }s1;
    61. struct strf{
    62. unsigned char id[4]; //块ID,固定为strf
    63. unsigned int size; //块大小,等于struct avi_strf_chunk去掉id和size的大小
    64. unsigned int size1; //size1含义和值同size一样
    65. unsigned int width; //视频主窗口宽度(单位:像素)
    66. unsigned int height; //视频主窗口高度(单位:像素)
    67. unsigned short planes; //始终为1
    68. unsigned short bitcount; //每个像素占的位数,只能是148162432中的一个
    69. unsigned char compression[4]; //视频流编码格式,如JPEG、MJPG等
    70. unsigned int image_size; //视频图像大小,等于width * height * bitcount / 8
    71. unsigned int x_pixels_per_meter; //显示设备的水平分辨率,设为0即可
    72. unsigned int y_pixels_per_meter; //显示设备的垂直分辨率,设为0即可
    73. unsigned int num_colors; //含义不清楚,设为0即可
    74. unsigned int imp_colors; //含义不清楚,设为0即可
    75. }q1;
    76. }w1;
    77. }a1;
    78. struct movi{
    79. unsigned char id[4];
    80. unsigned int size;
    81. unsigned char type[4];
    82. }movi1;
    83. }HEAD;
    84. #endif

  • 相关阅读:
    CoDeSys系列-1、CoDeSys了解及资料收集
    ​Qt for Python 入门¶​
    如何快速掌握JVM调优的基本方法和工具,如JConsole和VisualVM
    【NeurIPS && 图谱问答】知识图谱(KG) Mutil-Hop推理的锥形嵌入方法(中科院--含源码)
    第6章 MyBatis框架入门详解(1)
    Flume学习笔记:01-Flume的安装与简单入门示例
    ARM-day2
    深度学习目标检测模型综述
    Jackson关于Western Blot、IHC 和 ELISA 的显色检测分析
    STM32 寄存器配置笔记——USART配置 打印
  • 原文地址:https://blog.csdn.net/m0_59802969/article/details/133985672