www.pudn.com > mediator15src.zip > AudioCodecEnumerator.cpp


/* 
 * AudioCodecEnumerator.cpp 
 * Copyright (C) 2002 Arno Hornberger  
 * Original Version Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com 
 * 
 * This file is part of MPEG Mediator, a free MPEG stream converter. 
 * 
 * MPEG Mediator is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * MPEG Mediator is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */ 
 
#include "AudioCodecEnumerator.h" 
 
BOOL CALLBACK acmDriverEnumCallback(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport); 
BOOL CALLBACK acmFormatEnumCallback(HACMDRIVERID hadid, LPACMFORMATDETAILS pafd,  
                                    DWORD dwInstance, DWORD fdwSupport); 
 
BOOL CALLBACK acmFormatTagEnumCallback(HACMDRIVERID hadid, LPACMFORMATTAGDETAILS paftd,   
                                       DWORD dwInstance, DWORD fdwSupport); 
 
bool AudioCodecEnumerator::IsEnumerated(HACMDRIVERID hadid, WAVEFORMATEX *wfx, int cbSize, int *dwFormatTagIdx, int *FormatIdx) 
{ 
	if (!wfx || !cbSize) 
		return false; 
 
  for (int i = 0; i < m_vAudioCodecList.GetSize(); i++) 
  { 
		if (m_vAudioCodecList[i].hadid != hadid) 
			continue; 
 
    for (int j = 0; j < m_vAudioCodecList[i].m_vWaveFormatExList.GetSize(); j++) 
    { 
      CWaveFormatEx wfxTemp; 
 
      wfxTemp = m_vAudioCodecList[i].m_vWaveFormatExList[j]; 
 
      if (wfxTemp.GetSize() == cbSize) 
      { 
        if (wfxTemp.Get()->wFormatTag       == wfx->wFormatTag     && 
            wfxTemp.Get()->wBitsPerSample   == wfx->wBitsPerSample && 
            wfxTemp.Get()->nSamplesPerSec   == wfx->nSamplesPerSec && 
            wfxTemp.Get()->nChannels        == wfx->nChannels      && 
            wfxTemp.Get()->nAvgBytesPerSec  == wfx->nAvgBytesPerSec) 
        { 
          *dwFormatTagIdx = i; 
          *FormatIdx = j; 
          return true; 
        } 
      } 
    } 
  } 
  return false; 
} 
 
void AudioCodecEnumerator::Enumerate(LPWAVEFORMATEX lpwfx) 
{ 
	m_nSampleFreq     = lpwfx->nSamplesPerSec; 
  m_nChannels       = lpwfx->nChannels; 
  m_nBitsPerSample  = lpwfx->wBitsPerSample; 
   
  m_vAudioCodecList.RemoveAll(); 
  acmDriverEnum(acmDriverEnumCallback, (DWORD)this, ACM_DRIVERENUMF_NOLOCAL); 
} 
 
BOOL CALLBACK acmDriverEnumCallback(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport) 
{ 
  AudioCodecEnumerator *audEnum = (AudioCodecEnumerator *)dwInstance; 
  HACMDRIVER had; 
  ACMFORMATTAGDETAILS aftd; 
 
	audEnum->m_add.cbStruct = sizeof(ACMDRIVERDETAILS); 
	 
	if (acmDriverDetails(hadid, &audEnum->m_add, 0)) 
		return TRUE; 
 
  if (!acmDriverOpen(&had, hadid, 0)) 
  { 
		audEnum->m_hHad = had; 
    memset(&aftd, 0, sizeof(ACMFORMATTAGDETAILS)); 
    aftd.cbStruct = sizeof(ACMFORMATTAGDETAILS); 
    acmFormatTagEnum(had, &aftd, acmFormatTagEnumCallback, (DWORD)audEnum, 0); 
    acmDriverClose(had, 0); 
  } 
  return TRUE; 
} 
 
BOOL CALLBACK acmFormatTagEnumCallback(HACMDRIVERID hadid, LPACMFORMATTAGDETAILS paftd, 
				 															 DWORD dwInstance, DWORD fdwSupport) 
{ 
  AudioCodecEnumerator *audEnum = (AudioCodecEnumerator *)dwInstance; 
  ACMFORMATDETAILS afd; 
  WAVEFORMATEX *wfx; 
  DWORD max_size_format; 
 
	if (paftd->dwFormatTag == WAVE_FORMAT_PCM) 
		return TRUE; 
 
	acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &max_size_format); 
   
  wfx = (WAVEFORMATEX *)new char[max_size_format]; 
 
  memset(wfx, 0, sizeof(WAVEFORMATEX)); 
  wfx->nChannels        = audEnum->m_nChannels; 
  wfx->nSamplesPerSec   = audEnum->m_nSampleFreq; 
  wfx->wFormatTag       = (WORD)paftd->dwFormatTag; 
  wfx->wBitsPerSample   = audEnum->m_nBitsPerSample; 
  wfx->nBlockAlign      = wfx->nChannels * wfx->wBitsPerSample / 8; 
  wfx->nAvgBytesPerSec  = wfx->nBlockAlign * wfx->nSamplesPerSec; 
 
  memset(&afd, 0, sizeof(ACMFORMATDETAILS)); 
  afd.pwfx          = wfx; 
  afd.cbStruct      = sizeof(ACMFORMATDETAILS); 
  afd.cbwfx         = max_size_format; 
  afd.dwFormatTag   = paftd->dwFormatTag; 
 
  strcpy(audEnum->szTempFormatTag, paftd->szFormatTag); 
   
  acmFormatEnum(audEnum->m_hHad, &afd, acmFormatEnumCallback,  
								(DWORD)audEnum, ACM_FORMATENUMF_WFORMATTAG); 
   
  delete [](char *)wfx; 
 
  return TRUE; 
} 
 
BOOL CALLBACK acmFormatEnumCallback(HACMDRIVERID hadid, LPACMFORMATDETAILS pafd,  
																	  DWORD dwInstance, DWORD fdwSupport) 
{ 
  AudioCodecEnumerator *audEnum = (AudioCodecEnumerator *)dwInstance; 
   
  WAVEFORMATEX wfxSrc; 
  HACMSTREAM has; 
   
  AudioCodecEnumerator::CAudioCodecInfo cnfo;  
   
  if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) 
  {  
    // try to open a stream with our pcm input 
 
    wfxSrc.cbSize           = 0; 
    wfxSrc.nChannels        = audEnum->m_nChannels; 
    wfxSrc.nSamplesPerSec   = audEnum->m_nSampleFreq; 
    wfxSrc.wFormatTag       = WAVE_FORMAT_PCM; 
    wfxSrc.wBitsPerSample   = audEnum->m_nBitsPerSample; 
    wfxSrc.nBlockAlign      = wfxSrc.nChannels * wfxSrc.wBitsPerSample / 8; 
    wfxSrc.nAvgBytesPerSec  = wfxSrc.nBlockAlign * wfxSrc.nSamplesPerSec; 
     
    if (!acmStreamOpen(&has, audEnum->m_hHad, &wfxSrc, pafd->pwfx, NULL, 0, 0, ACM_STREAMOPENF_QUERY)) 
    { 
      // conversion is supported. 
      if (!audEnum->m_vAudioCodecList.GetSize() ||  
					audEnum->m_vAudioCodecList.GetSize() && 
					((audEnum->m_vAudioCodecList[0].formatTag != pafd->dwFormatTag) || (audEnum->m_vAudioCodecList[0].hadid != hadid))) 
      { 
        cnfo.hadid       = hadid; 
        cnfo.formatTag   = pafd->dwFormatTag; 
        strcpy(cnfo.szFormatTag, audEnum->szTempFormatTag); 
        audEnum->m_vAudioCodecList.InsertAt(0, cnfo); 
      } 
      // finally copy the stream format to the tag list 
       
      AudioCodecEnumerator::CWaveFormatEx wfx; 
      wfx.SetSize(pafd->cbwfx); 
      memcpy(wfx.GetData(), pafd->pwfx, pafd->cbwfx); 
 
      audEnum->m_vAudioCodecList[0].m_vWaveFormatExList.InsertAt(0, wfx); 
      audEnum->m_vAudioCodecList[0].m_vFormatDetailsList.InsertAt(0, *pafd); 
    } 
  } 
  return TRUE; 
} 
 
const CArray&  
				AudioCodecEnumerator::GetEnumeratedCodecs() 
{ 
	return m_vAudioCodecList; 
}