视频采集、视频压缩

1.引言

      视频的采集和压缩是进行视频传输、监控等视频应用开发时必须采取的步骤。 
      关于视频采集,本文探讨了一种基于Windows平台的简单而实用的方法,利用微软提供的VFW(Video For Windows)软件包来实现,只需要有一般的USB摄像头,就可以方便地对视频进行采集和保存。 
   
视频压缩方面,本文探讨了如何利用现阶段压缩率最大、传输可靠性最高的一种编码标准—H.264标准的开源编码器(T264)来实现对采集到的视频文件进行压缩的方法,利用VFW 所采集到的视频格式是没有进行任何压缩的AVI 格式,首先对AVI 格式进行转换,再利用T264源码对转换后的视频流文件进行压缩编码,这样就极大地压缩了视频文件,方便视频的传输。

2.视频信息的采集

    由于利用VFW软件包能够方便地实现视频、音频数据流到AVI文件的存储,在Visual C++中将VFW软件包的函数封装成为AVICAP窗口类函数,利用AVICAP窗口类函数,程序员能够通过发送消息或设置属性来捕获、播放和编辑视频剪辑,能灵活地实现从模拟视频源采集数字视频信号,并将捕捉的视频流存储到磁盘或者直接对视频缓存进行处理。
    
本文所述的方法是在Viusal C++ 6.0 软件平台上实现的,而软件实现的具体步骤如下: 
    1)在采集视频前必须先创建一个视频采集的窗口,以及添加一些具体的操作按钮,窗口利用函数capCreateCaptureWindow 来创建,如果窗口创建成功,返回窗口的句柄(程序中hwndV),如果创建不成功,则返回NULL 值。具体的创建程序及注释如下: 
       hwndV=capCreateCaptureWindow(
      (LPSTR) "My Capture Window",   //捕捉窗口名称
              
 WS_CHILD | WS_VISIBLE,       //窗口风格样式 
                        150, 150, 300, 280,          //窗口位置和大小 
                        (HWND) hwndMain,             //父窗口句柄 
               
(int) 1);                    //窗口标识
       2)采集开始前,要将采集窗口与视频设备相关联,VFW接口采用capDriverConnect (hWndCap,,nIndex)这个函数,式中:hWndCap所建立的视频捕捉窗口的句柄;nIndex为查询得到的视频卡驱动程序的索引号。接下来,获取视频采集设备的能力及状态信息,VFW中采用函数capDriverGetCaps(hwnd,psCaps,wsize)来得到采集设备的能力,而采用capGetStatus (hwnd,s,size)函数来得到采集设备的状态信息。
       3)启动显示模式并设置其模式参数,AVICAP  窗口类采用两个函数来实现,具体程序和注释如下:  
       capPreviewRate( hwndVideo, 66); //设置预览播放速率 
        capreview( hwndVideo, TRUE);   //启动预览模式 

      4)采集视频流并保存,并终止视频采集并断开与采集设备的连接,在程序的开头定义一个结构体OPENFN,用于初始化一个对话框,而这个对话框是用来保存视频的对话框。
  具体程序如下: 
 if (!isRecordFileOpen)

      OPENFN ofname;     //打开文件结构体
       ZeroMemory(&ofname, sizeof(OPENFN)); //初始化结构体 
      ofname.lStructSize = sizeof(OPENFN);    //结构体的大小 
      ofname.hwndOwner = hwndMain;            //主窗口句柄 
     ofname.lpstrFile = recordFile;         //保存的文件指针 
     ofname.nMaxFile = sizeof(recordFile);   //保存文件的大小 
      ofname.lpstrFilter = "Video/0*.avi";   //保存文件的后缀 
      ofname.nFilterIndex = 1;               //文件索引号 
      ofname.lpstrFileTitle = NULL;          //文件名指针 
      ofname.nMaxFileTitle = 0; 
    ofname.lpstrInitialDir = NULL; 
    ofname.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST; 

     if(GetSaveFileName(&ofn) == TRUE)    //显示保存文件的对话框
     {
       strcpy(recordFile, ofn.lpstrFile);
       strcat(recordFile, ".avi");
       isRecordFileOpen = true;
     }
 } 

        设置好保存文件以后,需用函数CreateThread来创建一个录像的线程在其中采集视频流,并利用函数capDriverDisconnect 来终止视频采集并断开与采集设备的连接,录像线程的具体代码如下:

       DWORD id;                          //创建一个录像线程
          SECURITY_ATTRIBUTES ma;
       ma.nLength = sizeof(SECURITY_ATTRIBUTES);
       ma.lpSecurityDescriptor = NULL;
       ma.bInheritHandle = TRUE;
       hVideoThread = (&ma, (ULONG)0,
       videoThreadProc, (LPVOID)(ULONG)0, (ULONG)0, &id);

3.视频格式的转换

     本文所采用的是基于H.264编码标准的视频压缩方法,所利用的源码是由中国视频编码自由组织联合开发的t264编×××,在使用本源码前,编码器要求进行压缩的文件格式应为YUV 格式视频文件,而VFW采集到的视频文件是最原始的AVI 格式,因而要进行格式的转换 。 
       从AVI格式到YUV 格式的转换,并没有直接的公式,而AVI视频文件流的每一帧对应一个BMP(RGB)文件,则可以利用公式转换成YUV 文件,转换的公式如下:
     Y = 0.299R + 0.587G + 0.114B
     Cb = 0.564(B – Y )
     Cr = 0.713(R -Y )

      其中,Cb 对应U,Cr 对应V,分别表示构成彩色的两个分量,而在程序中,则通过以下的程序来实现(按4:2:0 采样格式):
      void RGB2YUV ( uint8 R, uint8 G, uint8 B, uint8 *y, uint8 *u, uint8 *v )
   {
     *y = Clip ( ( ( 66 * int(R) + 129 * int(G) + 25 * int(B) + 128) >> 8) + 16 );
     *u = Clip ( ( ( -38 * int(R) – 74 * int(G) + 112 * int(B) + 128) >> 8) + 128 );
     *v = Clip ( ( ( 112 * int(R) – 94 * int(G) – 18 * int(B) + 128) >> 8) + 128 );
   }

4.利用编码器进行压缩编码

     由中国视频编码自由组织联合开发的编码器在基于VisualC++平台上创建了一个console程序,而前述的视频采集程序因为有窗口、按钮等视图窗口,故是一个windows程序,在Visual C++平台中,要将console 程序和windows 程序很好地结合在一起使用,是个很复杂的过程,因此,可以在前面视频采集程序里面运用一个C++函数ShellExecute 来调用编码器函数。
    具体实现的步骤如下:

    1)首先针对采集后经格式转换生成的YUV文件,得到它的帧数目,在配置文件enconfig.txt修改编码帧的数目,例如如果帧数目为100,将enconfig.txt 文件中的第6、7、8 行: 
     300 # total frame number
    300 # i intervals
    300 # idr intervals 

     改为 :
    100 # total frame number 
    100 # i intervals
    100 # idr intervals

     帧数目修改以后,文件生成的路径也应该改为最终exe 文件生成的路径,在enconfig.txt的最后三行进行修改。
    1)编译编码器,是采用的CONSOLE 程序,一般是在命令行中来执行exe 程序,而本文中的方法是利用入口函数main(int argc, char* argv[])的特征,其中,argc 表示参数的个数,而argv[]数组用于保存参数的指针,在程序中就对参数进行赋值,省去了进入命令行进行执行的繁琐过程,从而生成一个可以直接拿来运用的exe 程序。具体赋值语句如下:
     argv[0]="T264.exe";
   argv[1]="-e";
   argv[2]="enconfig.txt";

   2)设置t264.exe 文件路径,上述的过程中已经生成一个可执行的t264.exe 文件,如果将YUV文件放在与之相同的目录下,在调试运行这个程序的时候就可以生成264码流文件,达到编码的目的。但本文是需要将采集、压缩编码在同一个程序中完成,因而把生成的t264.exe文件复制到采集程序的调试目录下面。
3)上述的工作都做好以后,可以在采集程序里面调用编码器程序了,这时用一个函数来
实现,具体代码是:  
           ShellExecute(NULL,"open","t264.exe",
       "T264.exe –e enconfig.txt",NULL,SW_SHOWNORMAL);

      其中,SW_SHOWNORMAL 指的是一种程序运行风格,此时代表正常运行,在调用时可以看到程序运行的全部过程(DOS命令窗口显示),如果需要程序透明执行,不可见,则可以用SW_HIDE 来代替它。 
      至此,整个视频采集、格式转换与编码压缩的过程就全部完成了,本文中所采集的AVI文件大小为4.075M,经格式转换后的YUV 文件大小为5.458M,而最终生成的264 码流大小只有27k,压缩率达到了150.9倍。

5.总结 

   本文所探讨的从视频采集、格式转换到压缩编码的整个过程,可以简单方便地完成,可以直接应用在视频监控或者视频的网络传输等的前期开发。佰锐科技已为视频监控音视频即时通讯提供了解决方案。http://www.bairuitech.com

对于本博客有任何问题的朋友可加Q:992139738

原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/192020.html

(0)
上一篇 2021年11月14日
下一篇 2021年11月14日

相关推荐

发表回复

登录后才能评论