你的位置:首页 > 操作系统

[操作系统]关于 AVI 的一些代码


 

#ifndef __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__#define __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__/**************************************************************************************************\ * 2012-05-31 关于avi的一些功能。 (1) 由于丢帧等问题,导致录像长度不对,根据录像时间和帧数,修正avi文件中的帧率信息  auto_avi::ReviseAviFrameRate(sec, frame, file);  auto_avi::ReviseAviFrameRate_ms(millsec, frame, file); \**************************************************************************************************/#include <auto_file.h>#include <__time.h>class auto_avi{public:  auto_avi()  {  };  ~auto_avi()  {  }public:  /**************************************************************************************************\  * static void      :    * ReviseAviFrameRate  :  修正avi录像的长度(修改文件头里面的信息,把帧率修改为实际的帧率)  * DWORD nSeconds    :  录像长度  * DWORD nFrame     :  总帧数  * LPCTSTR pszFile    :    \**************************************************************************************************/  static void ReviseAviFrameRate(DWORD nSeconds, DWORD nFrame, LPCTSTR pszFile)  {    auto_file f;    if (!f.Open(pszFile, GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING, 0))      return;    SetFilePointer(f.m_hFile, 0x80, 0, FILE_BEGIN);    DWORD scale = 1000;    DWORD rate = nFrame * 1000 / nSeconds;    f.OverWrite((LPBYTE)&scale, 4);    f.OverWrite((LPBYTE)&rate, 4);  }  /**************************************************************************************************\  * static void       :    * ReviseAviFrameRate_ms  :  指定毫秒的版本  * DWORD nMilliSeconds   :  录像长度毫秒  * DWORD nFrame       :  帧率  * LPCTSTR pszFile     :  录像文件  \**************************************************************************************************/  static void ReviseAviFrameRate_ms(DWORD nMilliSeconds, DWORD nFrame, LPCTSTR pszFile)  {    auto_file f;    if (!f.Open(pszFile, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING, 0))    {      return;    }    if (nFrame == 0)    {      SetFilePointer(f.m_hFile, 0x8c, 0, FILE_BEGIN);      if (!f.Read((LPBYTE)&nFrame, 4))        return;    }    SetFilePointer(f.m_hFile, 0x80, 0, FILE_BEGIN);    DWORD scale = 1000;    ULONGLONG a = nFrame;    a *= 1000000;    a /= nMilliSeconds;    DWORD rate = (DWORD)a;    f.OverWrite((LPBYTE)&scale, 4);    f.OverWrite((LPBYTE)&rate, 4);  }};#endif

#ifndef __HSS_AUTO_AVI_HSS__#define __HSS_AUTO_AVI_HSS__#include <StringN.h>#include <HBuffer.H>class auto_avi_icc{public:  auto_avi_icc()  {    __memzero(m_Com);    __memzero(param):    __memzero(strhdr);    m_pFile = 0;    tStartTime = 0;    psz = 0;  }  ~auto_avi_icc()  {  }  struct  {    BITMAPINFOHEADER bmi;    BITMAPINFOHEADER bmo;  }param;private:  BOOL InitCompress()  {    //利用代码选择压缩器    __memzero(m_Com);    m_Com.cbSize = sizeof(m_Com);    m_Com.dwFlags = ICMF_COMPVARS_VALID;       m_Com.fccType = ICTYPE_VIDEO;     m_Com.lFrame = 0;     m_Com.lKey = 3;    //关键帧    m_Com.lKeyCount = 3;     m_Com.lDataRate = 780;    m_Com.lpbiOut = (BITMAPINFO*)&m_OutInfo;     //压缩MPG4格式    //m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M', 'P', '4', '2'), ICMODE_COMPRESS);    //压缩DIVX    //m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('D', 'I', 'V', 'X'), ICMODE_COMPRESS);    //压缩H264    m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('X', '2', '6', '4'), ICMODE_COMPRESS);    m_Com.cbState = 1180;    //ICCompressorChoose(NULL,ICMF_CHOOSE_ALLCOMPRESSORS ,(LPVOID)&m_InInfo,NULL,&m_Com,"选择压缩类型");    ICCompressGetFormat(m_Com.hic, (LPBITMAPINFO)&param.bmi, (LPBITMAPINFO)&param.bmo);    int ret = ICCompressBegin(m_Com.hic, (LPBITMAPINFO)&param.bmi, (LPBITMAPINFO)&param.bmo);    if(ret != ICERR_OK )    {      //MessageBox(NULL, "视频压缩器无法启动!", "系统提示", MB_ICONSTOP);      return FALSE;    }    return TRUE;  }  BOOL CreateAviFile(LPCTSTR pszFileName, LPBITMAPINFOHEADER pbi, LPBITMAPINFOHEADER pbo)  {    param.bmi = *pbi;    param.bmo = *pbo;    m_IndexFrame = 0 ;    //AVI文件初始化    AVIFileInit();    //设置压缩参数    if(!InitCompress())    {      AVIFileExit();      return FALSE;    }    //打开文件    m_pFile = NULL;    HRESULT hr = ::AVIFileOpen(&m_pFile, pszFileName, OF_WRITE|OF_CREATE, NULL);      if(hr != 0)      {       AVIFileExit();      //MessageBox(NULL, "无法创建视频文件!", "系统提示", MB_ICONSTOP);      return 0;      }         memset(&strhdr, 0, sizeof(strhdr)) ;      strhdr.fccType = streamtypeVIDEO;//  stream  type      strhdr.fccHandler = 0;      strhdr.dwScale = 1;      strhdr.dwRate = iLuxFrameRate;     //  25  fps     //int WIDTH = (m_InInfo.bmiHeader.biWidth * m_InInfo.bmiHeader.biBitCount + 31) / 32 * 4;    //strhdr.dwSuggestedBufferSize = WIDTH * m_InInfo.bmiHeader.biHeight;    strhdr.dwSuggestedBufferSize = m_InInfo.bmiHeader.biWidth * m_InInfo.bmiHeader.biHeight * 3;          SetRect(&strhdr.rcFrame,       0,       0,       m_InInfo.bmiHeader.biWidth,       m_InInfo.bmiHeader.biHeight);        hr = AVIFileCreateStream(m_pFile, &ps, &strhdr);         if (hr != AVIERR_OK)    {      AVIFileExit();      //MessageBox(NULL, "无法创建视频文件!", "系统提示", MB_ICONSTOP);      return 0;      }    tStartTime = GetTickCount();        return true;  }  void CloseAviFile()  {    //结束数据压缩    if (m_Com.hic)    {      ICCompressEnd(m_Com.hic);      //关闭压缩句柄      ICClose(m_Com.hic);      if(ps)         AVIStreamClose(ps);             if(m_pFile)         AVIFileClose(m_pFile);            AVIFileExit();    }  }  BOOL AddFrame(LPBITMAPINFOHEADER pbih, LPBYTE pBits)  {      char* buffer = new char [NWIDTH * NHEIGHT * 3 + 1];      memset(buffer, 0, NWIDTH * NHEIGHT * 3 + 1);      DWORD dwCkID = 0;      DWORD dwCompFlags = 0;      DWORD dwQuality = 100;      iLuxFrameRate = 25;      DWORD m_RealFrame = ((GetTickCount() - tStartTime) * iLuxFrameRate + 500) / 1000;      long cj = m_RealFrame - m_IndexFrame;      for(long i = 0; i < cj + 1; i ++)      {        //视频压缩        memset(buffer, 0, NWIDTH * NHEIGHT * 3 + 1);        if(ICCompress(m_Com.hic, 0, &m_OutInfo.bmiHeader, buffer,          &m_InInfo.bmiHeader, (unsigned char *)pBuffer, &dwCkID, &dwCompFlags, m_IndexFrame ++, 0, dwQuality, NULL, NULL) == ICERR_OK)        {          AVIStreamSetFormat(ps, m_IndexFrame, &m_OutInfo.bmiHeader, sizeof(m_OutInfo.bmiHeader));          VERIFY(0 == AVIStreamWrite(ps, //stream  pointer              m_IndexFrame  , //time of this  frame              1, //number  to  write              (LPBYTE) buffer, //pBuffer,             m_OutInfo.bmiHeader.biSizeImage, //size  of  this  frame              AVIIF_KEYFRAME,  //  flags....              NULL,              NULL));          OutputDebugString(".");        }        else        {          VERIFY(0);        }      }      delete []buffer;  }private:  COMPVARS  m_Com;  PAVIFILE  m_pFile; //AVI文件  AVISTREAMINFO strhdr; //AVI流信息  PAVISTREAM  ps; //AVI流指针  DWORD    tStartTime;  HBuffer    m_BufFrame;};#endif

#ifndef __HSS_AVI_STREAM_HSS__#define __HSS_AVI_STREAM_HSS__/**************************************************************************************************\ * 2013-09-08 新的监控录像类,自动持续录像,改变录像大小,叠加文字等,但是没有图像缓冲区  auto_avi_stream avi; avi.SetConfigFile avi.Open(... avi.AddFrame avi.Close(\**************************************************************************************************/#include <auto_x264.h>#include <rjpeg.h>#include <auto_IplImage.h>#include <HBuffer.h>#include <timemath.h>#include <overtext.h>#include <StringN.h>#define FCCX264      (*(DWORD*)"X264")class auto_avi_stream{public:  struct  {  }param;  struct  {    char        szFileName[_MAX_PATH];    DWORD        fccHandler;    RJPEG_OPEN      Param;    BITMAPINFOHEADER  bih;    ULONGLONG      lTickBegin;    SYSTEMTIME      stBegin;    ULONGLONG      lFrameIndex;  //下一帧的索引    ULONGLONG      lFrameCount;    ULONGLONG      lTickEnd;    SYSTEMTIME      stEnd;        BOOL        fFirstRun;  }info;  auto_x264    m_264;  HBuffer      m_BufResized;  HBuffer      m_BufOverlayText;public:  auto_avi_stream()  {    __memzero(param);    __memzero(info);  }  ~auto_avi_stream()  {  }  /**************************************************************************************************\  * void        :  2013年9月8日 设置配置文件,x264会自动把后缀修改为 .x264.cfg  * SetConfigFile   :    * LPCTSTR pszFile  :    \**************************************************************************************************/  void SetConfigFile(LPCTSTR pszFile)  {    __strcpy(m_264.param.szConfigFile, pszFile);  }  /**************************************************************************************************\  * BOOL   :  2013年9月8日 是否打开  * IsOpen  :    \**************************************************************************************************/  BOOL IsOpen()  {    if (info.fccHandler == FCCX264)      return m_264.IsOpen();    return FALSE;  }  /**************************************************************************************************\  * BOOL          :  2013年9月8日 打开录像  * Open          :    * LPCTSTR pszFile    :  文件名(可以是模板)  * DWORD fccHandler    :  编码,*(DWORD*)"X264"(FCCX264)  * RJPEG_OPEN* param   :  录像参数  * DWORD dwTick = 0    :  开始时刻  * SYSTEMTIME* pst = 0  :  开始时间  \**************************************************************************************************/  BOOL Open(LPCTSTR pszFile, DWORD fccHandler, RJPEG_OPEN* param, DWORD dwTick = 0, SYSTEMTIME* pst = 0)  {    if (param->Format.nFrameRate <= 0)      return FALSE;    info.Param = *param;    info.fccHandler = fccHandler;    __strcpy(info.szFileName, pszFile);    if (dwTick == 0 || pst == 0)    {      info.lTickBegin = ::GetTickCount();      GetLocalTime(&info.stBegin);    }    else    {      info.lTickBegin = dwTick;      info.stBegin = *pst;    }    info.lTickEnd = info.lTickBegin;    info.stEnd = info.stBegin;    info.lFrameCount = 0;    BITMAPINFOHEADER bih = {0};    info.bih.biBitCount = 24;    info.bih.biWidth = info.Param.Format.biWidth;    info.bih.biHeight = info.Param.Format.biHeight;    info.bih.biPlanes = 1;    info.bih.biSize = sizeof(info.bih);    info.bih.biSizeImage = (info.bih.biWidth * info.bih.biBitCount + 31) / 32 * 4 * info.bih.biHeight;    char szf[_MAX_PATH] = {0};    GetFileName(szf, info.szFileName, &info.stBegin);    return Open(szf);  }  /**************************************************************************************************\  * BOOL            :  2013年9月8日 增加帧  * AddFrame          :  会自动停止等  * DWORD dwTick        :    * LPBITMAPINFOHEADER pbih  :    * LPBYTE pBits        :    \**************************************************************************************************/  BOOL AddFrame(DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits)  {    if (pbih->biBitCount != 24)      return FALSE;    ULONGLONG tick = GetTickCount(dwTick);    //帧率控制    double sec = (double)(LONGLONG)(tick - info.lTickBegin) / 1000.0;    ULONGLONG index = (ULONGLONG)(LONGLONG)(sec * info.Param.Format.nFrameRate + 0.5);    if (index <= info.lFrameIndex && info.lTickEnd != info.lTickBegin)      return TRUE;    info.lFrameIndex = index;    info.lTickEnd = tick;    SYSTEMTIME stold = info.stEnd;    SYSTEMTIME st = info.stBegin;    SystemTimeAdd(&st, (int)(LONGLONG)(tick - info.lTickBegin));    info.stEnd = st;    //先看看是否需要改变大小    if (pbih->biWidth != info.bih.biWidth      || pbih->biHeight != info.bih.biHeight      )    {      int size = info.bih.biSizeImage;      LPBYTE p = m_BufResized.GetBuffer(size);      if (p == 0)        return FALSE;            auto_IplImage src(pbih, pBits);      if (!src)        return FALSE;      auto_IplImage dst(&info.bih, p);      if (!dst)        return FALSE;      cvResize(src, dst, CV_INTER_LINEAR );      pbih = &info.bih;      pBits = p;    }    //叠加文字    if (info.Param.oiText[0])    {      //第一步,如果没有改变大小,则要复制一下内存,防止改变了原始内存      if (pBits != m_BufResized.m_pBuffer)      {        int size = info.bih.biSizeImage;        LPBYTE p = m_BufResized.GetBuffer(size);        if (p == 0)          return FALSE;        ASSERT(info.bih.biSizeImage == pbih->biSizeImage);        memcpy(p, pBits, pbih->biSizeImage);        pBits = p;        pbih = &info.bih;      }            //下面做实际的叠加文字      Overlay(pbih, pBits, info.stEnd, info.lFrameIndex);    }    //增加到录像    if (!CompressFrame(tick, pbih, pBits))      return FALSE;    info.lFrameCount ++;    BOOL bStop = 0;    if (info.Param.dwFileEveryMinutes)    {      if (info.Param.dwFileEveryMinutes == 1)      {        if (info.stEnd.wSecond < stold.wSecond)        {          double sec = GetSeconds();          if (sec > 30)          {            bStop = TRUE;          }        }      }      else if ((info.stEnd.wMinute % info.Param.dwFileEveryMinutes) == 0)      {        double sec = GetSeconds();        if (sec > info.Param.dwFileEveryMinutes * 60.0 / 2.0)        {          bStop = TRUE;        }      }    }    else if (info.Param.dwSecondsLimit)    {      double sec = GetSeconds();      if (sec >= info.Param.dwSecondsLimit)      {        bStop = TRUE;      }    }    if (bStop)    {      //停止录像,开始新录像      Stop();      char szf[_MAX_PATH] = {0};      if (0 == GetFileName(szf, info.szFileName, &info.stEnd))      {        //非模板,直接关闭        return TRUE;      }      info.lTickBegin = tick;      info.lTickEnd = tick;      info.stBegin = info.stEnd;      return Open(szf);    }    return TRUE;  }  /**************************************************************************************************\  * double    :  2013年9月8日 录像时间长度  * GetSeconds  :    \**************************************************************************************************/  double GetSeconds()  {    double sec = (double)(LONGLONG)(info.lTickEnd - info.lTickBegin) / 1000.0;    if (sec < 1.0)      sec = 1.0;    return sec;  }  /**************************************************************************************************\  * DWORD    :  2013年9月8日 录像多少帧  * GetFrames  :    \**************************************************************************************************/  DWORD GetFrames()  {    return (DWORD)info.lFrameCount;  }  /**************************************************************************************************\  * void   :  2013年9月8日 关闭  * Close  :    \**************************************************************************************************/  void Close()  {    Stop();  }  /**************************************************************************************************\  * void     :  2013年9月8日 配置  * Config    :    * HWND hwnd  :    \**************************************************************************************************/  void Config(HWND hwnd)  {    if (info.fccHandler == FCCX264)    {      m_264.Config(hwnd);    }  }  /**************************************************************************************************\  * LPCTSTR    :  2013年9月8日 获取文件名  * GetFileName  :    \**************************************************************************************************/  LPCTSTR GetFileName()  {    if (info.fccHandler == FCCX264)    {      return m_264.info.szFile;    }    return "";  }  /**************************************************************************************************\  * double     :  2013年9月8日 获取实际的帧率  * GetFrameRate  :    \**************************************************************************************************/  double GetFrameRate()  {    return GetFrames() / GetSeconds();  }  /**************************************************************************************************\  * void     :  2013年9月8日 获取当前录像的信息  * GetInfo   :    * char* psz  :    * int cb    :    * int& n    :    \**************************************************************************************************/  void GetInfo(char* psz, int cb, int& n, int mode = 0)  {    double sec = GetSeconds();    LPCTSTR stm = "秒";    if (sec > 3600.0)    {      sec /= 3600.0;      stm = "时";    }    else if (sec > 60.0)    {      sec /= 60.0;      stm = "分";    }    if (mode == 0)    {      if (info.fccHandler == FCCX264)      {        __snprintcat2(psz, cb, n), "%.1lf%s, 帧%d, 帧率%.1lf\n#录像文件:%s%s%s",          sec, stm,          GetFrames(),          GetFrameRate(),          GetFileName(),           m_264.info.szAsciiFile[0] ? "\n#临时文件:" : "",          m_264.info.szAsciiFile          );      }      else      {        __snprintcat2(psz, cb, n), "%s, %.1lf%s, 帧%d, 帧率%.1lf",          GetFileName(),          sec, stm,          GetFrames(),          GetFrameRate()          );      }    }  }private:  /**************************************************************************************************\  * void  :  2013年9月8日 停止  * Stop  :    \**************************************************************************************************/  void Stop()  {    if (info.fccHandler == FCCX264)    {      m_264.Close();    }  }  /**************************************************************************************************\  * BOOL            :  2013年9月8日 压缩一帧  * CompressFrame       :    * ULONGLONG dwTick      :    * LPBITMAPINFOHEADER pbih  :    * LPBYTE pBits        :    \**************************************************************************************************/  BOOL CompressFrame(ULONGLONG dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits)  {    BOOL retval = 0;    if (info.fccHandler == FCCX264)    {      retval = m_264.AddFrame(dwTick, pbih, pBits);    }    return retval;  }  /**************************************************************************************************\  * ULONGLONG    :  2013年9月8日 防止毫秒时刻转回来  * GetTickCount  :    * DWORD dwTick  :    \**************************************************************************************************/  ULONGLONG GetTickCount(DWORD dwTick)  {    ULONGLONG t = dwTick;    if (dwTick < info.lTickEnd)    {      t += 0x100000000;    }    return t;  }  /**************************************************************************************************\  * BOOL        :  2013年9月8日 内部使用打开录像文件  * Open        :    * LPCTSTR pszFile  :    \**************************************************************************************************/  BOOL Open(LPCTSTR pszFile)  {    if (info.fccHandler == FCCX264)      return m_264.Open(pszFile, &info.bih);    return FALSE;  }  /**************************************************************************************************\  * int          :  2013年9月8日 把文件模板转成真正的文件名  * GetFileName      :  返回替换的模板个数  * char* pszFile     :    * LPCTSTR pszTemplate  :    * SYSTEMTIME* pst    :    \**************************************************************************************************/  int GetFileName(char* pszFile, LPCTSTR pszTemplate, SYSTEMTIME* pst)  {    CString szf(pszTemplate);    int nr = 0;    char szi[8] = {0};    __sprintf(szi), "%04d", pst->wYear);    nr += szf.Replace("{y}", szi);    __sprintf(szi), "%02d", pst->wMonth);    nr += szf.Replace("{m}", szi);    __sprintf(szi), "%02d", pst->wDay);    nr += szf.Replace("{d}", szi);    __sprintf(szi), "%02d", pst->wHour);    nr += szf.Replace("{h}", szi);    __sprintf(szi), "%d", pst->wHour);    nr += szf.Replace("{H}", szi);    __sprintf(szi), "%02d", pst->wMinute);    nr += szf.Replace("{M}", szi);    __sprintf(szi), "%02d", pst->wSecond);    nr += szf.Replace("{s}", szi);    __strncpy(pszFile, (LPCTSTR)szf, _MAX_PATH);    return nr;  }  /**************************************************************************************************\  * LPBYTE           :  2013年9月8日 叠加文字  * Overlay           :    * LPBITMAPINFOHEADER pdbih  :    * LPBYTE pdBits        :    * SYSTEMTIME st        :    * DWORD lFrameIndex      :    \**************************************************************************************************/  LPBYTE Overlay(LPBITMAPINFOHEADER pdbih, LPBYTE pdBits, SYSTEMTIME st, DWORD lFrameIndex)  {    //叠加文字    if (info.Param.oiText[0])    {      //计算时间      //把[T]替换为时间,把[F]替换为帧号[t]为简写时间      char szt[64] = {0};      char szT[64] = {0};      char szm[64] = {0};      __sprintf(szT), "%04d年%02d月%02d日 %02d:%02d:%02d",        st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);      __sprintf(szt), "%04d-%02d-%02d %02d:%02d:%02d",        st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);      __sprintf(szm), "%03d", st.wMilliseconds);      char szf[32] = {0};      __sprintf(szf), "%d", lFrameIndex);      CString szOverlay(info.Param.oiText);      szOverlay.Replace("[T]", szT);      szOverlay.Replace("[t]", szt);      szOverlay.Replace("[F]", szf);      szOverlay.Replace("[m]", szm);      szOverlay.Replace("[N]", "\r\n");      if (_OT_GetTextBitmap(&m_BufOverlayText, &info.Param.oiFormat.lfFont, szOverlay, pdbih->biWidth))      {        OT_FLAGS of = {0};        of.nPositionType = 0;              //0 位置 1 下面水平条        of.nPositionX = info.Param.oiFormat.nPosX;      //位置坐标        of.nPositionY = info.Param.oiFormat.nPosY;      //位置坐标        of.lfFont.lfFont = info.Param.oiFormat.lfFont;    //字体和颜色(前景)        of.lfFont.rgbFont = info.Param.oiFormat.crColor;        of.nBkTransparent = 100 - info.Param.oiFormat.nBackGround * 25;        of.nEdgeWidth = info.Param.oiFormat.nEdgeWidth;      //边框宽度(用背景颜色)边框        of.crBackground = RGB(0, 0, 0);        of.nTransparent = 0;    //100 全透明 0 背景颜色(背景)        of.bAutoWhiteBlack = info.Param.oiFormat.bAutoWhiteBlack;  //2011年11月29日 自动黑白字        _OT_OverTextBitmap4(&m_BufOverlayText, pdbih, pdBits, pdbih->biSizeImage,          FALSE,          0,          0,          &of);      }    }    return pdBits;  }};#endif

#ifndef __HSS_AVI_ENC_HSS__#define __HSS_AVI_ENC_HSS__/**************************************************************************************************\ * 2013-08-31 新的压缩avi类,更简单,并且支持数据流(但是可能不理想,先展示不管了) 关于配置文件的处理: 可以设置配置文件,若没有设置配置文件,则使用缺省的配置,不进行配置的相关处理和调用 因为很多编码器都可以保存配置,保存为缺省 现在必须处理配置,是因为保存的位置可能被写保护,所以必须保存到其他地方 (1) 若指定了配置文件,则自动装载配置文件,并检查配置文件是否匹配,如果匹配则使用,如果不匹配,则不使用 (2) 若没有指定配置文件,则使用缺省 (3) 若指定了配置文件,必须显式调用配置函数,否则不进行自动的配置 配置:   m_enc.param.fccHandler = *(DWORD*)"X264";//"XVID";  m_enc.param.lKey = 3;  m_enc.param.lFrameRate = 12;  m_enc.param.szConfigFile...  m_enc.Config(GetSafeHwnd()); 用法:   m_enc.param.fccHandler = *(DWORD*)"X264";//"XVID";  m_enc.param.lKey = 3;  m_enc.param.lFrameRate = 12;  m_enc.Open(pbih);  m_enc.AddFrame(tick, pbih, pbits, &Buf);  if (!Buf.IsEmpty())  {    //写入avi文件  }\**************************************************************************************************/#include <StringN.h>#include <auto_file.h>#include <mmsystem.h> #include <vfw.h> #include <__dbg.h>#include <HBuffer.h>#include <auto_folder.h>#include <auto_buffer.h>#pragma comment(lib, "vfw32.lib")typedef struct _AVIENC_CONFIGFILE{  DWORD    mask;      //acfg  COMPVARS  cv;}AVIENC_CONFIGFILE;class auto_avienc{public:  struct  {    DWORD      fccHandler;    // handler of chosen compressor or    long      lFrameRate;    // 帧率    long      lKey;      // 关键帧数量    long      lDataRate;    //码率    long      lQ;        //质量    char      szConfigFile[_MAX_PATH];  //文件    DWORD      bChooseFccHandler : 1;    // 选择压缩编码器  }param;  struct  {    ULONGLONG    uTickBegin;      //开始帧的时刻    ULONGLONG    uTickEnd;      //最后一帧时刻    LONG      lFrameIndex;    //最后一帧索引    BITMAPINFO    in;    BITMAPINFO    out;  }info;  auto_buffer      m_Buf;        //压缩和状态内存, ICINFO, STATE  HIC          m_hic;          BOOL        m_bLoaded;      //是否装载过配置public:  auto_avienc()  {    __memzero(param);    __memzero(info);    m_hic = 0;    m_bLoaded = 0;    param.fccHandler = *(DWORD*)"WMV3";    param.lFrameRate = 15;    param.lKey = 20;    param.lDataRate = 0;    param.bChooseFccHandler = 1;  }  ~auto_avienc()  {    Close();  }  /**************************************************************************************************\  * BOOL   :  2013年9月1日 是否打开  * IsOpen  :    \**************************************************************************************************/  BOOL IsOpen()  {    return m_hic != 0;  }  /**************************************************************************************************\  * void     :  2013年9月1日 是否成功没有关系  * LoadConfig  :    \**************************************************************************************************/  void LoadConfig()  {    if (param.szConfigFile[0] == 0 || m_bLoaded)      return;    if (!auto_file::Read(param.szConfigFile, &m_Buf))      return;    if (m_Buf.m_p == 0 || m_Buf.m_size == 0 || m_Buf.m_size < sizeof(ICINFO))    {      m_Buf.free();      return;    }        ICINFO* pi = (ICINFO*)m_Buf.m_p;    if (pi->dwSize != sizeof(ICINFO))    {      m_Buf.free();      return;    }    if (param.fccHandler == 0 || param.bChooseFccHandler)  //使用保存的编码器类型    {      param.fccHandler = pi->fccHandler;      __trace_file "usering %X", param.fccHandler);__trace_end;    }    m_bLoaded = TRUE;  }  /**************************************************************************************************\  * BOOL      :  2013年8月31日 这个检查是否配置正确,如果配置正确,则使用,不正确则不使用  * CheckConfig  :    \**************************************************************************************************/  BOOL CheckConfig()  {    if (m_hic == 0)      return FALSE;    if (!m_Buf)      return FALSE;    ICINFO in = {0};        if (0 == ICGetInfo(m_hic, &in, sizeof(in)))    {      __trace_file "");__trace_end;      return FALSE;    }    ICINFO* pi = (ICINFO*)(LPBYTE)m_Buf;    if (memcmp(pi, &in, sizeof(in)) != 0)    {      __trace_file "");__trace_end;      return FALSE;    }    DWORD size = ICGetStateSize(m_hic);    if (size != m_Buf.m_size - sizeof(ICINFO))    {      __trace_file "");__trace_end;      return FALSE;    }    LPBYTE pState = (LPBYTE)(m_Buf.m_p) + sizeof(ICINFO);    if (0 == ICSetState(m_hic, pState, size))    {      __trace_file "");__trace_end;      return FALSE;    }    __trace_file "");__trace_end;    return TRUE;  }  /**************************************************************************************************\  * BOOL     :  2013年8月31日 配置信息,导入以前保存的配置,如果导入的配置不对,则重新显示对话框配置  * Config    :    * HWND hwnd  :  2013年9月1日 修改,如果fccHandler是0,则显示配置也选择的对话框。  如果fccHandler指定,则只配置指定的  \**************************************************************************************************/  BOOL Config(HWND hwnd)  {    LoadConfig();      //可能没装载就调用了Config    //2013年9月1日    HIC hic = 0;    if (param.fccHandler == 0 || param.bChooseFccHandler)    {      COMPVARS cv = {0};      cv.cbSize = sizeof(cv);      cv.fccType = ICTYPE_VIDEO;      cv.fccHandler = param.fccHandler;      cv.dwFlags = ICMF_COMPVARS_VALID;      if (!ICCompressorChoose(hwnd, ICMF_CHOOSE_ALLCOMPRESSORS|ICMF_CHOOSE_KEYFRAME|ICMF_CHOOSE_DATARATE, 0, 0, &cv, 0))      {        __trace_file "%X", param.fccHandler);__trace_end;        return FALSE;      }      hic = cv.hic;      param.fccHandler = cv.fccHandler;      if (cv.lKey)        param.lKey = cv.lKey;      if (cv.lDataRate)        param.lDataRate = cv.lDataRate;    }    else    {      hic = ICOpen(ICTYPE_VIDEO, param.fccHandler, ICMODE_COMPRESS|ICMODE_FASTCOMPRESS);      if (hic == 0)        return FALSE;      //下面这句话可能不对,因为XVID这个返回没有,但是实际上有对话框      //if (ICERR_OK != ICQueryConfigure(hic))      //  goto LABLE_CLOSE_HIC;      if (ICERR_OK != ICConfigure(hic, hwnd))      {        ICClose(hic);        return FALSE;      }    }    //保存配置,用于下次使用    BOOL bSucc = 0;    int size = ICGetStateSize(hic);    LPBYTE p = m_Buf.alloc(size + sizeof(ICINFO));    if (p)    {      m_Buf.zero();      if (0 != ICGetInfo(hic, (ICINFO*)p, sizeof(ICINFO)))      {        p += sizeof(ICINFO);        if (ICERR_OK == ICGetState(hic, p, size))        {          if (param.szConfigFile[0])          {            auto_folder af(param.szConfigFile);            if (auto_file::Write(param.szConfigFile, &m_Buf))            {              bSucc = TRUE;            }          }          else          {            bSucc = TRUE;          }        }      }    }    ICClose(hic);    if (!bSucc)    {      m_Buf.free();    }    return bSucc;  }  /**************************************************************************************************\  * BOOL            :  2013年8月31日 打开指定格式的录像,准备录像  * Open            :    * LPBITMAPINFOHEADER pbih  :    \**************************************************************************************************/  BOOL Open(LPBITMAPINFOHEADER pbih)  {    //关闭    Close();    info.in.bmiHeader = *pbih;    info.out.bmiHeader = *pbih;    //初始化压缩类型    if (param.fccHandler == 0)      param.fccHandler = *(DWORD*)"XVID";    //装载配置,如果设置了 ,则自动更新为保存中的fccHandler    //LoadConfig();    m_hic = ICOpen(ICTYPE_VIDEO, param.fccHandler, ICMODE_COMPRESS|ICMODE_FASTCOMPRESS);    if (m_hic == 0)      return FALSE;    __trace_file "fcc = %X", param.fccHandler);__trace_end;    CheckConfig();    if (ICERR_OK != ICCompressGetFormat(m_hic, &info.in, &info.out))      return FALSE;    if (ICERR_OK != ICCompressBegin(m_hic, &info.in, &info.out))      return FALSE;    return TRUE;  }  /**************************************************************************************************\  * BOOL            :  增添一帧,根据时刻判断帧率,及是否抛弃  * AddFrame          :    * DWORD dwTick        :    * LPBITMAPINFOHEADER pbih  :    * LPBYTE pBits        :    * HBuffer* pBufOut      :    \**************************************************************************************************/  BOOL AddFrame(DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits, HBuffer* pBufOut)  {    if (m_hic == 0)      return FALSE;    if (pbih->biWidth != info.in.bmiHeader.biWidth      || pbih->biHeight != info.in.bmiHeader.biHeight      || pbih->biBitCount != info.in.bmiHeader.biBitCount      )    {      return FALSE;    }    if (dwTick == 0)    {      if (info.uTickBegin == 0)      {        info.uTickBegin = GetTickCount();        info.uTickEnd = info.uTickBegin;        info.lFrameIndex = 0;      }      else      {        info.lFrameIndex ++;      }    }    else    {      ULONGLONG tick_end = 0;      if (info.uTickBegin == 0)      {        info.uTickBegin = dwTick;        tick_end = dwTick;      }      else if (dwTick < info.uTickEnd)      {        //循环了        tick_end = dwTick + 0x100000000;      }      else      {        tick_end = dwTick;      }      int dIndex = (int)(double((LONGLONG)(tick_end - info.uTickBegin)) / 1000.0 * param.lFrameRate + 0.5);      if (dIndex && dIndex <= info.lFrameIndex)      {        return TRUE;      }      info.uTickEnd = tick_end;      info.lFrameIndex = dIndex;    }    LPBYTE pOut = pBufOut->GetBuffer(__max(info.out.bmiHeader.biSizeImage, info.in.bmiHeader.biSizeImage));    if (pOut == 0)      return FALSE;    DWORD dwCkID = 0;    DWORD dwCompFlags = 0;    DWORD dwQuality = 0;    if(ICCompress(m_hic,       ((info.lFrameIndex % param.lKey) == 0 ? ICCOMPRESS_KEYFRAME : 0),       &info.out.bmiHeader,       pOut,      pbih,       (unsigned char *)pBits,       &dwCkID,       &dwCompFlags,       (LONG)info.lFrameIndex,       0,       dwQuality,       NULL,       NULL      ) != ICERR_OK)    {      return FALSE;    }    //__trace_file "size=%d\r\n", info.out.bmiHeader.biSizeImage);__trace_end;    pBufOut->m_nBuffer = info.out.bmiHeader.biSizeImage;    return TRUE;  }  /**************************************************************************************************\  * void   :  2013年8月31日 关闭  * Close  :    \**************************************************************************************************/  void Close()  {    if (m_hic)    {      ICCompressEnd(m_hic);        ICClose(m_hic);      m_hic = 0;    }  }};#endif