media.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 27k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "pch.h"
  2. #include "resource.h"
  3. #include "media.h"
  4. #define FOURCC_INFO mmioFOURCC('I','N','F','O')
  5. #define FOURCC_DISP mmioFOURCC('D','I','S','P')
  6. #define FOURCC_IARL mmioFOURCC('I','A','R','L')
  7. #define FOURCC_IART mmioFOURCC('I','A','R','T')
  8. #define FOURCC_ICMS mmioFOURCC('I','C','M','S')
  9. #define FOURCC_ICMT mmioFOURCC('I','C','M','T')
  10. #define FOURCC_ICOP mmioFOURCC('I','C','O','P')
  11. #define FOURCC_ICRD mmioFOURCC('I','C','R','D')
  12. #define FOURCC_ICRP mmioFOURCC('I','C','R','P')
  13. #define FOURCC_IDIM mmioFOURCC('I','D','I','M')
  14. #define FOURCC_IDPI mmioFOURCC('I','D','P','I')
  15. #define FOURCC_IENG mmioFOURCC('I','E','N','G')
  16. #define FOURCC_IGNR mmioFOURCC('I','G','N','R')
  17. #define FOURCC_IKEY mmioFOURCC('I','K','E','Y')
  18. #define FOURCC_ILGT mmioFOURCC('I','L','G','T')
  19. #define FOURCC_IMED mmioFOURCC('I','M','E','D')
  20. #define FOURCC_INAM mmioFOURCC('I','N','A','M')
  21. #define FOURCC_IPLT mmioFOURCC('I','P','L','T')
  22. #define FOURCC_IPRD mmioFOURCC('I','P','R','D')
  23. #define FOURCC_ISBJ mmioFOURCC('I','S','B','J')
  24. #define FOURCC_ISFT mmioFOURCC('I','S','F','T')
  25. #define FOURCC_ISHP mmioFOURCC('I','S','H','P')
  26. #define FOURCC_ISRC mmioFOURCC('I','S','R','C')
  27. #define FOURCC_ISRF mmioFOURCC('I','S','R','F')
  28. #define FOURCC_ITCH mmioFOURCC('I','T','C','H')
  29. #define FOURCC_VIDC mmioFOURCC('V','I','D','C')
  30. #define mmioWAVE    mmioFOURCC('W','A','V','E')
  31. #define mmioFMT     mmioFOURCC('f','m','t',' ')
  32. #define mmioDATA    mmioFOURCC('d','a','t','a')
  33. #define MAXNUMSTREAMS   50 
  34. static HANDLE STDMETHODCALLTYPE GetRiffInfo( HMMIO hmmio )
  35. {
  36.     MMCKINFO    ck;
  37.     MMCKINFO    ckINFO;
  38.     MMCKINFO    ckRIFF;
  39.     HANDLE      h = NULL;
  40.     LONG        lSize;
  41.     DWORD       dw;
  42.     BOOL        fDoneDISP;
  43.     BOOL        fDoneINFO;
  44.     BOOL        fDoneName;
  45.     LPSTR pInfo;
  46.     if (!hmmio)
  47.         return NULL ;
  48.     mmioSeek(hmmio, 0, SEEK_SET);
  49.     /* descend the input file into the RIFF chunk */
  50.     if( mmioDescend( hmmio, &ckRIFF, NULL, 0 ) != 0 )
  51.         goto error;
  52.     if( ckRIFF.ckid != FOURCC_RIFF )
  53.         goto error;
  54.     fDoneDISP = fDoneINFO = fDoneName = FALSE;
  55.     while (!(fDoneDISP && fDoneINFO) && !mmioDescend(hmmio, &ck, &ckRIFF, 0))
  56.     {
  57.         if (ck.ckid == FOURCC_DISP)
  58.         {
  59.             /* Read dword into dw, break if read unsuccessful */
  60.             if (mmioRead(hmmio, (char*)&dw, sizeof(dw)) != (LONG)sizeof(dw))
  61.                 goto error;
  62.             /* Find out how much memory to allocate */
  63.             lSize = ck.cksize - sizeof(dw);
  64.             if ((int)dw == CF_DIB && h == NULL)
  65.             {
  66.                 /* get a handle to memory to hold the description and 
  67.                     lock it down */
  68.                 if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  69.                     goto error;
  70.                 if (mmioRead(hmmio, (char*)GlobalLock(h), lSize) != lSize)
  71.                     goto error;
  72.                 fDoneDISP = TRUE;
  73.             }
  74.             else if ((int)dw == CF_TEXT)
  75.             {
  76.                 pInfo = (LPSTR)LocalAlloc(LPTR, lSize+1);//+1 not required I think
  77.                 if (!pInfo)
  78.                     goto error;
  79.                 if (!mmioRead(hmmio, pInfo,  lSize))
  80.                     goto error;
  81.                 //AddInfoToList(pmmpsh, pInfo, ck.ckid );
  82.                 fDoneName = TRUE;
  83.             }
  84.         }
  85.         else if (ck.ckid    == FOURCC_LIST &&
  86.                  ck.fccType == FOURCC_INFO &&
  87.                  !fDoneINFO)
  88.         {
  89.             while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
  90.             {
  91.                 switch (ckINFO.ckid)
  92.                 {
  93.                     case FOURCC_ISBJ:
  94.                     case FOURCC_INAM:
  95.                     case FOURCC_ICOP:
  96.                     case FOURCC_ICRD:
  97.                     case FOURCC_IART:
  98.                     case FOURCC_ICMS:
  99.                     case FOURCC_ICMT:        
  100.                     case FOURCC_ICRP:
  101.                     case FOURCC_IDIM:
  102.                     case FOURCC_IARL:
  103.                     case FOURCC_IDPI:
  104.                     case FOURCC_IENG:
  105.                     case FOURCC_IGNR:
  106.                     case FOURCC_IKEY:        
  107.                     case FOURCC_ILGT:
  108.                     case FOURCC_IMED:
  109.                     case FOURCC_IPLT:
  110.                     case FOURCC_IPRD:
  111.                     case FOURCC_ISFT:
  112.                     case FOURCC_ISHP:
  113.                     case FOURCC_ISRC:
  114.                     case FOURCC_ISRF:
  115.                     case FOURCC_ITCH:
  116.                         pInfo = (LPSTR)LocalAlloc(LPTR, ck.cksize+1);//+1 not required I think
  117.                         if (!pInfo)
  118.                             goto error;
  119.                         if (!mmioRead(hmmio, pInfo,  ck.cksize))
  120.                             goto error;
  121.                         //AddInfoToList(pmmpsh, pInfo, ckINFO.ckid);
  122.                         if (ckINFO.ckid == FOURCC_INAM)
  123.                             fDoneName = TRUE;
  124.                         break;
  125.                 }
  126.                 if (mmioAscend(hmmio, &ckINFO, 0))
  127.                     break;
  128.             }
  129.         }
  130.         /* Ascend so that we can descend into next chunk
  131.          */
  132.         if (mmioAscend(hmmio, &ck, 0))
  133.             break;
  134.     }
  135.     goto exit;
  136. error:
  137.     if (h)
  138.     {
  139.         GlobalUnlock(h);
  140.         GlobalFree(h);
  141.     }
  142.     h = NULL;
  143. exit:
  144.     return h;
  145. }
  146. STDMETHODIMP GetMidiInfo( LPCTSTR pszFile, PMIDIDESC pmidi )
  147. {
  148. #ifdef _MIDI_PROPERTY_SUPPORT_
  149.     MCI_OPEN_PARMS      mciOpen;    /* Structure for MCI_OPEN command */
  150.     DWORD               dwFlags;
  151.     DWORD               dw;
  152.     MCIDEVICEID         wDevID;
  153.     MCI_STATUS_PARMS    mciStatus;
  154.     MCI_SET_PARMS       mciSet;        /* Structure for MCI_SET command */
  155.     MCI_INFO_PARMS      mciInfo;  
  156.         /* Open a file with an explicitly specified device */
  157.     mciOpen.lpstrDeviceType = TEXT("sequencer");
  158.     mciOpen.lpstrElementName = pszFile;
  159.     dwFlags = MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE;
  160.     dw = mciSendCommand((MCIDEVICEID)0, MCI_OPEN, dwFlags,(DWORD_PTR)(LPVOID)&mciOpen);
  161.     if (dw)
  162.         return E_FAIL ;
  163.     wDevID = mciOpen.wDeviceID;
  164.     mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
  165.     dw = mciSendCommand(wDevID, MCI_SET, MCI_SET_TIME_FORMAT,
  166.         (DWORD_PTR) (LPVOID) &mciSet);
  167.     if (dw)
  168.     {
  169.         mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD)0);
  170.         return E_FAIL ;
  171.     }
  172.     mciStatus.dwItem = MCI_STATUS_LENGTH;
  173.     dw = mciSendCommand(wDevID, MCI_STATUS, MCI_STATUS_ITEM,
  174.         (DWORD_PTR) (LPTSTR) &mciStatus);
  175.     if (dw)
  176.         pmidi->nLength = 0;
  177.     else
  178.         pmidi->nLength = (UINT)mciStatus.dwReturn;
  179.     mciInfo.dwCallback  = 0;
  180.     mciInfo.lpstrReturn = pmidi->szMidiCopyright;
  181.     mciInfo.dwRetSize   = sizeof(pmidi->szMidiCopyright);
  182.     *mciInfo.lpstrReturn = 0 ;
  183.     mciSendCommand(wDevID, MCI_INFO,  MCI_INFO_COPYRIGHT, (DWORD_PTR)(LPVOID)&mciInfo);
  184.     mciInfo.lpstrReturn = pmidi->szMidiCopyright;
  185.     mciInfo.dwRetSize   = sizeof(pmidi->szMidiSequenceName);
  186.     *mciInfo.lpstrReturn = 0 ;
  187.     mciSendCommand(wDevID, MCI_INFO,  MCI_INFO_NAME, (DWORD_PTR)(LPVOID)&mciInfo);
  188.     mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD)0);
  189.     return S_OK ;
  190. #else  _MIDI_PROPERTY_SUPPORT_
  191.     return E_FAIL;
  192. #endif _MIDI_PROPERTY_SUPPORT_
  193. }
  194. //-------------------------------------------------------------------------//
  195. STDMETHODIMP  GetMidiProperty( 
  196.     IN REFFMTID reffmtid, 
  197.     IN PROPID pid, 
  198.     IN const MIDIDESC* pMidi, 
  199.     OUT PROPVARIANT* pVar )
  200. {
  201.     HRESULT hr = S_OK ;
  202.     return hr ;        
  203. }
  204. //-------------------------------------------------------------------------//
  205. //  Wave
  206. //-------------------------------------------------------------------------//
  207. static BOOL PASCAL NEAR ReadWaveHeader(HMMIO hmmio,
  208.     PWAVEDESC    pwd)
  209. {
  210.     BOOL        bRet = FALSE ;
  211.     MMCKINFO    mmckRIFF;
  212.     MMCKINFO    mmck;
  213.     WORD        wFormatSize ;
  214.     MMRESULT    wError;
  215.     ZeroMemory( pwd, sizeof(*pwd) ) ;
  216.     mmckRIFF.fccType = mmioWAVE;
  217.     if( (wError = mmioDescend(hmmio, &mmckRIFF, NULL, MMIO_FINDRIFF)) ) 
  218.     {
  219.         return FALSE;
  220.     }
  221.     
  222.     mmck.ckid = mmioFMT;
  223.     if( (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK)) ) 
  224.     {
  225.         return FALSE;
  226.     }
  227.     if( mmck.cksize < sizeof(WAVEFORMAT) ) 
  228.     {
  229.         return FALSE;
  230.     }
  231.     
  232.     wFormatSize = (WORD)mmck.cksize;
  233.     if( NULL != (pwd->pwfx = (PWAVEFORMATEX)new BYTE[wFormatSize]) )
  234.     {
  235.         if ((DWORD)mmioRead(hmmio, (HPSTR)pwd->pwfx, mmck.cksize) != mmck.cksize) 
  236.         {
  237.             goto retErr;
  238.         }
  239.         if (pwd->pwfx->wFormatTag == WAVE_FORMAT_PCM) 
  240.         {
  241.             if (wFormatSize < sizeof(PCMWAVEFORMAT)) 
  242.             {
  243.                 goto retErr;
  244.             }
  245.         } 
  246.         else if( (wFormatSize < sizeof(WAVEFORMATEX)) || 
  247.                  (wFormatSize < sizeof(WAVEFORMATEX) + pwd->pwfx->cbSize) ) 
  248.         {
  249.             goto retErr ;
  250.         }
  251.         if( (wError = mmioAscend(hmmio, &mmck, 0)) ) 
  252.         {
  253.             goto retErr ;
  254.         }
  255.         mmck.ckid = mmioDATA;
  256.         if( (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK)) ) 
  257.         {
  258.             goto retErr ;
  259.         }
  260.         pwd->dwSize = mmck.cksize;
  261.         return S_OK ;
  262.     }
  263. retErr:
  264.     delete [] (LPBYTE)pwd->pwfx ;
  265.     return E_FAIL ;
  266. }
  267. //-------------------------------------------------------------------------//
  268. // Retrieves text representation of format tag
  269. STDMETHODIMP  GetWaveFormatTag( PWAVEFORMATEX pwfx, LPTSTR pszTag, IN ULONG cchTag )
  270. {
  271.     ASSERT( pwfx ) ;
  272.     ASSERT( pszTag ) ;
  273.     ASSERT( cchTag ) ;
  274.     
  275.     ACMFORMATTAGDETAILS aftd;
  276.     ZeroMemory( &aftd, sizeof(aftd) ) ;
  277.     aftd.cbStruct    = sizeof(ACMFORMATTAGDETAILSW) ;
  278.     aftd.dwFormatTag = pwfx->wFormatTag ;
  279.     if( 0 == acmFormatTagDetails( NULL, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG) )
  280.     {
  281.         //  copy to output.
  282.         lstrcpyn( pszTag, aftd.szFormatTag, cchTag ) ;
  283.         return S_OK ;
  284.     }
  285.     return E_FAIL ;
  286. }
  287. //-------------------------------------------------------------------------//
  288. STDMETHODIMP GetWaveInfo( IN LPCTSTR pszFile, OUT PWAVEDESC p )
  289. {
  290.     HMMIO   hmmio ;
  291.     
  292.     if( NULL == (hmmio = mmioOpen( (LPTSTR)pszFile, NULL, MMIO_ALLOCBUF | MMIO_READ)) )
  293.         return E_FAIL ;
  294.     HRESULT hr = ReadWaveHeader(hmmio, p) ;
  295.     mmioClose( hmmio, 0 ) ;
  296.     if( SUCCEEDED( hr ) && p->pwfx )
  297.     {
  298.         // Retrieve text representation of format tag
  299.         GetWaveFormatTag( p->pwfx, p->szWaveFormat, ARRAYSIZE(p->szWaveFormat) ) ;
  300.     }
  301.     return hr ;
  302. }
  303. //-------------------------------------------------------------------------//
  304. STDMETHODIMP FreeWaveInfo( IN OUT PWAVEDESC p )
  305. {
  306.     if( !( p && sizeof(*p) == p->dwSize ) && p->pwfx )
  307.     {
  308.         delete [] p->pwfx ;
  309.         p->pwfx = NULL ;
  310.     }
  311.     return S_OK ;
  312. }
  313. //-------------------------------------------------------------------------//
  314. STDMETHODIMP  _getWaveAudioProperty(
  315.     IN REFFMTID reffmtid,
  316.     IN PROPID   pid,
  317.     IN const PWAVEFORMATEX pwfx,
  318.     OUT PROPVARIANT* pVar )
  319. {
  320.     USES_CONVERSION ;
  321.     
  322.     HRESULT hr = E_UNEXPECTED ;
  323.     TCHAR   szBuf[MAX_DESCRIPTOR],
  324.             szFmt[MAX_DESCRIPTOR] ;
  325.     PropVariantInit( pVar ) ;
  326.     *szBuf = *szFmt = 0 ;
  327.     if( pwfx && IsEqualGUID( reffmtid, FMTID_AudioSummaryInformation ) )
  328.     {
  329.         hr = S_OK ;
  330.         switch( pid )
  331.         {
  332.             case PIDASI_AVG_DATA_RATE:
  333.                 if( 0 >= pwfx->nAvgBytesPerSec )
  334.                     return E_FAIL ;
  335.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDASI_AVG_DATA_RATE_FMT,
  336.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  337.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  338.                            pwfx->nAvgBytesPerSec/1000, 
  339.                            pwfx->nAvgBytesPerSec%1000 ) ;
  340.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  341.                 pVar->vt      = VT_BSTR ;
  342.                 break ;
  343.             case PIDASI_SAMPLE_RATE:
  344.                 if( 0 >= pwfx->nSamplesPerSec )
  345.                     return E_FAIL ;
  346.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDASI_SAMPLE_RATE_FMT,
  347.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  348.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  349.                            pwfx->nSamplesPerSec/1000, 
  350.                            pwfx->nSamplesPerSec%1000 ) ;
  351.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  352.                 pVar->vt      = VT_BSTR ;
  353.                 break ;
  354.             case PIDASI_SAMPLE_SIZE:
  355.                 if( 0 >= pwfx->wBitsPerSample )
  356.                     return E_FAIL ;
  357.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDASI_SAMPLE_SIZE_FMT,
  358.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  359.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  360.                            (int)pwfx->wBitsPerSample ) ;
  361.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  362.                 pVar->vt      = VT_BSTR ;
  363.                 break ;
  364.                 
  365.             case PIDASI_CHANNEL_COUNT:
  366.             {
  367.                 if( 0 >= pwfx->nChannels )
  368.                     return E_FAIL ;
  369.                 UINT nIDS = pwfx->nChannels == 1 ? IDS_MONO : 
  370.                             pwfx->nChannels == 2 ? IDS_STEREO : 0 ;
  371.                 if( nIDS )
  372.                 {
  373.                     TCHAR szDescr[MAX_DESCRIPTOR] ;
  374.                     if( LoadString( _Module.GetResourceInstance(), nIDS,
  375.                                     szDescr, ARRAYSIZE(szDescr) ) )
  376.                     {
  377.                         wnsprintf( szBuf, ARRAYSIZE(szBuf), TEXT("%d %s"), 
  378.                                    (int)pwfx->nChannels,
  379.                                    szDescr ) ;
  380.                     }
  381.                     else
  382.                         nIDS = 0 ;
  383.                 }
  384.                 if( 0 == nIDS )
  385.                 {
  386.                     wnsprintf( szBuf, ARRAYSIZE(szBuf), TEXT("%d"), 
  387.                                (int)pwfx->nChannels ) ;
  388.                 }
  389.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  390.                 pVar->vt      = VT_BSTR ;
  391.                 break ;
  392.             }
  393.             
  394.             default:
  395.                 return E_UNEXPECTED ;
  396.         }
  397.     }
  398.     return hr ;
  399. }
  400. //-------------------------------------------------------------------------//
  401. STDMETHODIMP  GetWaveProperty( 
  402.     IN REFFMTID reffmtid, 
  403.     IN PROPID pid, 
  404.     IN const WAVEDESC* pWave, 
  405.     OUT PROPVARIANT* pVar )
  406. {
  407.     USES_CONVERSION ;
  408.     
  409.     HRESULT hr = E_FAIL ;
  410.     TCHAR   szBuf[MAX_DESCRIPTOR],
  411.             szFmt[MAX_DESCRIPTOR] ;
  412.     PropVariantInit( pVar ) ;
  413.     *szBuf = *szFmt = 0 ;
  414.     if( IsEqualGUID( reffmtid, FMTID_AudioSummaryInformation ) )
  415.     {
  416.         hr = S_OK ;
  417.         switch( pid )
  418.         {
  419.             case PIDASI_FORMAT:
  420.                 if( 0 == *pWave->szWaveFormat )
  421.                     return E_FAIL ;
  422.                 pVar->bstrVal = SysAllocString( T2W((LPTSTR)pWave->szWaveFormat) ) ;
  423.                 pVar->vt      = VT_BSTR ;
  424.                 break ;
  425.             case PIDASI_TIMELENGTH:
  426.                 if( 0 >= pWave->nLength )
  427.                     return E_FAIL ;
  428.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDASI_TIMELENGTH_FMT,
  429.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  430.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  431.                            pWave->nLength/1000, pWave->nLength%1000 ) ;
  432.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  433.                 pVar->vt      = VT_BSTR ;
  434.                 break ;
  435.             default:
  436.                 hr = E_UNEXPECTED ;
  437.                 
  438.         }
  439.     }
  440.     if( FAILED( hr ) )
  441.         hr = _getWaveAudioProperty( reffmtid, pid, pWave->pwfx, pVar ) ;
  442.         
  443.     return hr ;
  444. }
  445. //-------------------------------------------------------------------------//
  446. //  AVI 
  447. //-------------------------------------------------------------------------//
  448. STDMETHODIMP ReadAviStreams( LPCTSTR pszFile, DWORD dwFileSize, PAVIDESC pAvi )
  449. {
  450.     HRESULT         hr;
  451.     PAVIFILE        pfile;
  452.     PAVISTREAM      pavi;
  453.     PAVISTREAM      rgpavis[MAXNUMSTREAMS];    // the current streams
  454.     AVISTREAMINFO   avsi;
  455.     LONG            timeStart;            // cached start, end, length
  456.     LONG            timeEnd;
  457.     int             cpavi;
  458.     int             i;
  459.     if( FAILED( (hr = AVIFileOpen(&pfile, pszFile, 0, 0L)) ) )
  460.         return hr ;
  461.     for (i = 0; i <= MAXNUMSTREAMS; i++) 
  462.     {
  463.         if (AVIFileGetStream(pfile, &pavi, 0L, i) != AVIERR_OK)
  464.             break;
  465.         if (i == MAXNUMSTREAMS) 
  466.         {
  467.             AVIStreamRelease(pavi);
  468.             //DPF("Exceeded maximum number of streams");
  469.             break;
  470.         }
  471.         rgpavis[i] = pavi;
  472.     }
  473.     //
  474.     // Couldn't get any streams out of this file
  475.     //
  476.     if (i == 0)
  477.     {
  478.         //DPF("Unable to open any streams in %s", pszFile);
  479.         if (pfile)
  480.             AVIFileRelease(pfile);
  481.         return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) ;
  482.     }
  483.     cpavi = i;
  484.     //
  485.     // Start with bogus times
  486.     //
  487.     timeStart = 0x7FFFFFFF;
  488.     timeEnd   = 0;
  489.     //
  490.     // Walk through and init all streams loaded
  491.     //
  492.     for (i = 0; i < cpavi; i++) 
  493.     {
  494.         AVIStreamInfo(rgpavis[i], &avsi, sizeof(avsi));
  495.         switch(avsi.fccType) 
  496.         {
  497.             case streamtypeVIDEO:
  498.             {
  499.                 LONG cbFormat;
  500.                 LPBYTE lpFormat;
  501.                 ICINFO icInfo;
  502.                 HIC hic;
  503.                 DWORD dwTimeLen;
  504.                 USES_CONVERSION ;
  505.                 AVIStreamFormatSize(rgpavis[i], 0, &cbFormat);
  506.                 dwTimeLen           = AVIStreamEndTime(rgpavis[i]) - AVIStreamStartTime(rgpavis[i]);
  507.                 pAvi->cFrames       = avsi.dwLength ;
  508.                 pAvi->nFrameRate    = MulDiv(avsi.dwLength, 1000000, dwTimeLen);
  509.                 pAvi->nDataRate     = MulDiv(dwFileSize, 1000000, dwTimeLen)/1024 ;
  510.                 pAvi->nWidth        = RECTWIDTH( &avsi.rcFrame ) ;
  511.                 pAvi->nHeight       = RECTHEIGHT( &avsi.rcFrame ) ;
  512.                 lstrcpyn( pAvi->szStreamName, avsi.szName, ARRAYSIZE(pAvi->szStreamName) ) ;
  513.                 //  Retrieve raster info (compression, bit depth).
  514.                 lpFormat = new BYTE[cbFormat] ;
  515.                 if( (lpFormat = new BYTE[cbFormat]) != NULL )
  516.                 {
  517.                     AVIStreamReadFormat(rgpavis[i], 0, lpFormat, &cbFormat);
  518.                     hic = (HIC)ICLocate( FOURCC_VIDC, avsi.fccHandler, (BITMAPINFOHEADER*)lpFormat, 
  519.                                          NULL, (WORD)ICMODE_DECOMPRESS );
  520.                     
  521.                     if (hic || ((LPBITMAPINFOHEADER)lpFormat)->biCompression == 0)
  522.                     {
  523.                         if (((LPBITMAPINFOHEADER)lpFormat)->biCompression)
  524.                         {
  525.                             ICGetInfo(hic, &icInfo, sizeof(ICINFO));
  526.                             ICClose(hic);
  527.                             lstrcpy(pAvi->szCompression, W2T(icInfo.szName));
  528.                         }
  529.                         else
  530.                         {
  531.                             LoadString( _Module.GetResourceInstance(), IDS_UNCOMPRESSED, 
  532.                                          pAvi->szCompression, ARRAYSIZE(pAvi->szCompression) ) ;
  533.                         }
  534.                         pAvi->nBitDepth = ((LPBITMAPINFOHEADER)lpFormat)->biBitCount ;
  535.                     }
  536.                     delete [] lpFormat ;
  537.                 }
  538.                 else
  539.                     hr = E_OUTOFMEMORY ;
  540.                 break ;
  541.             }
  542.             case streamtypeAUDIO:
  543.             {
  544.                 LONG        cbFormat;
  545.                 AVIStreamFormatSize(rgpavis[i], 0, &cbFormat);
  546.                 if( (pAvi->pwfx = (PWAVEFORMATEX) new BYTE[cbFormat]) != NULL )
  547.                 {
  548.                     ZeroMemory( pAvi->pwfx, cbFormat ) ;
  549.                     if( SUCCEEDED( AVIStreamReadFormat(rgpavis[i], 0, pAvi->pwfx, &cbFormat) ) )
  550.                         GetWaveFormatTag( pAvi->pwfx, pAvi->szWaveFormat, ARRAYSIZE(pAvi->szWaveFormat) ) ;
  551.                 }
  552.                 break;
  553.             }
  554.             default:
  555.                 break;
  556.         }
  557.     //
  558.     // We're finding the earliest and latest start and end points for
  559.     // our scrollbar.
  560.     //  
  561.         timeStart = min(timeStart, AVIStreamStartTime(rgpavis[i]));
  562.         timeEnd   = max(timeEnd, AVIStreamEndTime(rgpavis[i]));
  563.     }
  564.     pAvi->nLength = (UINT)(timeEnd - timeStart);
  565.     for (i = 0; i < cpavi; i++) 
  566.     {
  567.         AVIStreamRelease(rgpavis[i]);
  568.     }
  569.     AVIFileRelease(pfile);
  570.     return S_OK ;
  571. }
  572. //-------------------------------------------------------------------------//
  573. STDMETHODIMP GetAviInfo( LPCTSTR pszFile, PAVIDESC pavi )
  574. {
  575.     HRESULT hr = E_UNEXPECTED ;
  576.     //  Retrieve the file size
  577.     HANDLE hFile = CreateFile( pszFile, 
  578.                                GENERIC_READ, 
  579.                                FILE_SHARE_READ,NULL, 
  580.                                OPEN_EXISTING, 
  581.                                FILE_ATTRIBUTE_NORMAL, 
  582.                                NULL);
  583.     if (INVALID_HANDLE_VALUE == hFile)
  584.     {
  585.         DWORD dwRet = GetLastError() ;
  586.         return ERROR_SUCCESS != dwRet ? HRESULT_FROM_WIN32( dwRet ) : E_UNEXPECTED ;
  587.     }
  588.     DWORD dwFileSize = GetFileSize((HANDLE)hFile, NULL);
  589.     CloseHandle( hFile ) ;
  590.     AVIFileInit();
  591.     hr = ReadAviStreams(pszFile, dwFileSize, pavi);
  592.     AVIFileExit();
  593.     return hr ;
  594. }
  595. //-------------------------------------------------------------------------//
  596. STDMETHODIMP FreeAviInfo( IN OUT PAVIDESC p )
  597. {
  598.     if( !( p && sizeof(*p) == p->dwSize ) && p->pwfx )
  599.     {
  600.         delete [] p->pwfx ;
  601.         p->pwfx = NULL ;
  602.     }
  603.     return S_OK ;
  604. }
  605. //-------------------------------------------------------------------------//
  606. STDMETHODIMP  GetAviProperty( 
  607.     IN REFFMTID reffmtid, 
  608.     IN PROPID pid, 
  609.     IN const AVIDESC* pAvi, 
  610.     OUT PROPVARIANT* pVar )
  611. {
  612.     USES_CONVERSION ;
  613.     
  614.     HRESULT hr = E_UNEXPECTED ;
  615.     TCHAR   szBuf[MAX_DESCRIPTOR],
  616.             szFmt[MAX_DESCRIPTOR] ;
  617.     PropVariantInit( pVar ) ;
  618.     *szBuf = *szFmt = 0 ;
  619.     if( IsEqualGUID( reffmtid, FMTID_VideoSummaryInformation ) )
  620.     {
  621.         hr = S_OK ;
  622.         switch( pid )
  623.         {
  624.             case PIDVSI_STREAM_NAME:
  625.                 if( 0 == *pAvi->szStreamName )
  626.                     return E_FAIL ;
  627.                 pVar->bstrVal = SysAllocString( T2W((LPTSTR)pAvi->szStreamName) ) ;
  628.                 pVar->vt      = VT_BSTR ;
  629.                 break ;
  630.             case PIDVSI_FRAME_COUNT:
  631.                 if( 0 >= pAvi->cFrames )
  632.                     return E_FAIL ;
  633.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), TEXT("%d"), pAvi->cFrames ) ;
  634.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  635.                 pVar->vt      = VT_BSTR ;
  636.                 break ;
  637.             case PIDVSI_TIMELENGTH:
  638.                 if( 0 >= pAvi->nLength )
  639.                     return E_FAIL ;
  640.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_TIMELENGTH_FMT,
  641.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  642.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  643.                            pAvi->nLength/1000, pAvi->nLength%1000 ) ;
  644.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  645.                 pVar->vt      = VT_BSTR ;
  646.                 break ;
  647.             case PIDVSI_FRAME_RATE:
  648.                 if( 0 >= pAvi->nFrameRate )
  649.                     return E_FAIL ;
  650.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_FRAME_RATE_FMT,
  651.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  652.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  653.                            pAvi->nFrameRate/1000, pAvi->nFrameRate%1000 ) ;
  654.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  655.                 pVar->vt      = VT_BSTR ;
  656.                 break ;
  657.             case PIDVSI_DATA_RATE:
  658.                 if( 0 >= pAvi->nDataRate )
  659.                     return E_FAIL ;
  660.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_DATA_RATE_FMT,
  661.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  662.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, 
  663.                            pAvi->nDataRate/1000, pAvi->nDataRate%1000 ) ;
  664.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  665.                 pVar->vt      = VT_BSTR ;
  666.                 break ;
  667.             case PIDVSI_FRAME_WIDTH:
  668.                 if( 0 >= pAvi->nWidth )
  669.                     return E_FAIL ;
  670.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_FRAME_WIDTH_FMT,
  671.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  672.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, pAvi->nWidth ) ;
  673.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  674.                 pVar->vt      = VT_BSTR ;
  675.                 break ;
  676.             case PIDVSI_FRAME_HEIGHT:
  677.                 if( 0 >= pAvi->nHeight )
  678.                     return E_FAIL ;
  679.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_FRAME_HEIGHT_FMT,
  680.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  681.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, pAvi->nHeight ) ;
  682.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  683.                 pVar->vt      = VT_BSTR ;
  684.                 break ;
  685.             case PIDVSI_SAMPLE_SIZE:
  686.                 if( 0 >= pAvi->nBitDepth )
  687.                     return E_FAIL ;
  688.                 VERIFY( LoadString( _Module.GetResourceInstance(), IDS_PIDVSI_SAMPLE_SIZE_FMT,
  689.                         szFmt, ARRAYSIZE(szFmt) ) ) ;
  690.                 wnsprintf( szBuf, ARRAYSIZE(szBuf), szFmt, pAvi->nBitDepth ) ;
  691.                 pVar->bstrVal = SysAllocString( T2W( szBuf ) ) ;
  692.                 pVar->vt      = VT_BSTR ;
  693.                 break ;
  694.             case PIDVSI_COMPRESSION:
  695.                 if( 0 == *pAvi->szCompression )
  696.                     return E_FAIL ;
  697.                 pVar->bstrVal = SysAllocString( T2W((LPTSTR)pAvi->szCompression) ) ;
  698.                 pVar->vt      = VT_BSTR ;
  699.                 break ;
  700.             default:
  701.                 hr = E_UNEXPECTED ;
  702.         }
  703.     }
  704.     else if( IsEqualGUID( reffmtid, FMTID_AudioSummaryInformation ) )
  705.     {
  706.         if( PIDASI_FORMAT == pid )
  707.         {
  708.             if( 0 == *pAvi->szWaveFormat )
  709.                 return E_FAIL ;
  710.             pVar->bstrVal = SysAllocString( T2W((LPTSTR)pAvi->szWaveFormat) ) ;
  711.             pVar->vt      = VT_BSTR ;
  712.             hr = S_OK ;
  713.         }
  714.     }
  715.     if( FAILED( hr ) )
  716.         hr = _getWaveAudioProperty( reffmtid, pid, pAvi->pwfx, pVar ) ;
  717.     return hr ;
  718. }