Video Sequence Compressor

#include <vfw.h>


void VideoSequenceCompressor::init(HIC hic, BITMAPINFO *pbiInput, BITMAPINFO *pbiOutput, long lQ, long lKeyRate) {
 ICINFO info;
 LRESULT res;
 int cbSizeIn, cbSizeOut;

 cbSizeIn = pbiInput->bmiHeader.biSize + pbiInput->bmiHeader.biClrUsed*4;
 cbSizeOut = pbiOutput->bmiHeader.biSize + pbiOutput->bmiHeader.biClrUsed*4;

 this->hic  = hic;
 this->pbiInput = (BITMAPINFO *) new char[cbSizeIn];
  this->pbiOutput = (BITMAPINFO *) new char[cbSizeOut];
 this->lKeyRate = lKeyRate;

 memcpy(this->pbiInput, pbiInput, cbSizeIn);
 memcpy(this->pbiOutput, pbiOutput, cbSizeOut);

 lKeyRateCounter = 1;

 // Retrieve compressor information.

 res = ICGetInfo(hic, &info, sizeof info);

 if (!res)
  throw "Unable to retrieve video compressor information.";

 // Analyze compressor.

 this->dwFlags = info.dwFlags;

 if (info.dwFlags & VIDCF_TEMPORAL) {
  if (!(info.dwFlags & VIDCF_FASTTEMPORALC)) {
   // Allocate backbuffer

   if (!(pPrevBuffer = new char[pbiInput->bmiHeader.biSizeImage]))
    throw "VideoSequenceCompressor::init - Memory allocation error";
  }
 }

 if (info.dwFlags & VIDCF_QUALITY)
  lQuality = lQ;
 else
  lQuality = 0;

 // Allocate destination buffer

 lMaxPackedSize = ICCompressGetSize(hic, pbiInput, pbiOutput);

 if (!(pOutputBuffer = new char[lMaxPackedSize]))
  throw "VideoSequenceCompressor::init - Memory allocation error";

 // Save configuration state.
 //
 // Ordinarily, we wouldn't do this, but there seems to be a bug in
 // the Microsoft MPEG-4 compressor that causes it to reset its
 // configuration data after a compression session.  This occurs
 // in all versions from V1 through V3.
 //
 // Stupid fscking Matrox driver returns -1!!!

 cbConfigData = ICGetStateSize(hic);

 if (cbConfigData > 0) {
  if (!(pConfigData = new char[cbConfigData]))
   throw "VideoSequenceCompressor::init - Memory allocation error";

  cbConfigData = ICGetState(hic, pConfigData, cbConfigData);

  // As odd as this may seem, if this isn't done, then the Indeo5
  // compressor won't allow data rate control until the next
  // compression operation!

  if (cbConfigData)
   ICSetState(hic, pConfigData, cbConfigData);
 }

 lMaxFrameSize = 0;
 lSlopSpace = 0;
}

bool VideoSequenceCompressor::GetInstalledCodecs()
{
  // Fill video codec list
  m_vInstalledCodecList.RemoveAll();
 
  ICINFO codecInfo;
  HIC hic;
  int i=0,j=0;
  for (i=0; ICInfo(ICTYPE_VIDEO, i, &codecInfo); i++)
  {
    hic = ICOpen(codecInfo.fccType, codecInfo.fccHandler, ICMODE_COMPRESS );
    if (hic)
    {
      if(codecInfo.fccType != ICTYPE_VIDEO)
      {
        ICClose(hic);
        continue;
      }
      // Find out the compressor name.
      ICGetInfo(hic, &codecInfo, sizeof(codecInfo));
     
      TVideoCodecInfo cnfo;
      cnfo.hic                   = hic;
      cnfo.fccHandler            = codecInfo.fccHandler;
      memcpy( cnfo.szDescription, codecInfo.szDescription, 128*sizeof(WCHAR) );
      memcpy( cnfo.szDriver     , codecInfo.szDriver     , 128*sizeof(WCHAR) );
      memcpy( cnfo.szName       , codecInfo.szName       , 16*sizeof(WCHAR) );

      // Get State
#if 1
      DWORD size;
      size = ICGetStateSize(hic);
      if( size )
      {
        PBYTE pv = new BYTE[size];
        ICGetState( hic, pv, size );
        cnfo.SetSettings( pv, size );
        cnfo.SetSettings1st( pv, size);
        cnfo.SetSettings2nd( pv, size );
        delete []pv;
      }
#endif
      m_vInstalledCodecList.SetAtGrow( j++, cnfo );
     
    }     
  }
  EnumerateVideoCodecs( 640, 480 );
  return true;
}

bool VideoSequenceCompressor::EnumerateVideoCodecs(int width, int height)
{
  // Fill video codec list
  m_vVideoCodecList.RemoveAll();
  BITMAPINFO       bmpInfo;
  BITMAPINFOHEADER bi;
 
  memset(&bi, 0, sizeof(BITMAPINFOHEADER));
  bi.biSize        = sizeof(BITMAPINFOHEADER);
  bi.biWidth       = width;
  bi.biHeight      = height;
  bi.biPlanes      = 1;
  bi.biBitCount    = 24;
  bi.biCompression = BI_RGB;
  bi.biSizeImage   = 0;
 
  bmpInfo.bmiHeader = bi;
 
  HIC hic;
  int i=0,j=0;
  for (i=0; i<m_vInstalledCodecList.GetSize(); i++)
  {
      hic = m_vInstalledCodecList[i].hic;

      DWORD dwSupportedFormats = 0;

      // RGB
      bmpInfo.bmiHeader.biCompression = BI_RGB;
      bmpInfo.bmiHeader.biBitCount    = 24;
      // Skip this compressor if it can't handle the format.
      dwSupportedFormats = ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_RGB32 : 0;

      // YV12
      bmpInfo.bmiHeader.biCompression = '21VY';
      bmpInfo.bmiHeader.biBitCount    = 12;
      // Skip this compressor if it can't handle the format.
      dwSupportedFormats |= ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_YV12 : 0;

      // YUY2
      bmpInfo.bmiHeader.biCompression = '2YUY';
      bmpInfo.bmiHeader.biBitCount    = 16;
      // Skip this compressor if it can't handle the format.
      dwSupportedFormats |= ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_YUY2 : 0;

      m_vInstalledCodecList[i].dwSupportedFormats = dwSupportedFormats;

      if( !dwSupportedFormats )
        continue;
 
      TVideoCodecInfo cnfo;
      cnfo = m_vInstalledCodecList[i];
   
      m_vVideoCodecList.SetAtGrow( j++, cnfo );
     
  }
  return true;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章