오디오 형식을 찾으려면
[이 페이지와 연결된 기능인 Windows Media Format 11 SDK는 레거시 기능입니다. 원본 판독기 및 싱크 작성기에 의해 대체되었습니다. 원본 판독기 및 싱크 작성기는 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 Windows Media Format 11 SDK 대신 소스 판독기 및 싱크 작성기를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]
다음 예제 코드에서는 지정한 조건과 일치하는 오디오 형식을 찾는 방법을 보여 줍니다. FindAudioFormat 함수는 사용하려는 채널 수, 샘플당 비트 및 샘플 속도를 포함하는 WAVEFORMATEX 구조체에 대한 포인터를 허용합니다. 함수는 이러한 요구 사항과 일치하는 형식을 찾으며 dwMaxRate 매개 변수를 초과하지 않는 가장 높은 비트 속도를 찾습니다. fAVSync를 TRUE로 설정하면 함수는 비디오와 동기화할 수 있는 형식의 유효성만 검사합니다. 간단히 하기 위해 이 함수는 1단계 CBR 형식에서만 작동합니다.
// This constant is used to determine if an index was found.
#define INVALID_INDEX 0xFFFF
// The FindAudioFormat function finds a compressed audio format that
// matches the criteria defined by the input parameters.
HRESULT FindAudioFormat(GUID SubType,
WAVEFORMATEX* pWaveLimits,
DWORD dwMaxRate,
BOOL fAVSync,
IWMStreamConfig** ppStreamConfig)
{
HRESULT hr = S_OK;
IWMProfileManager* pProfileMgr = NULL;
IWMCodecInfo3* pCodecInfo = NULL;
IWMStreamConfig* pStreamConfig = NULL;
IWMStreamConfig* pBestMatch = NULL;
IWMMediaProps* pProps = NULL;
WM_MEDIA_TYPE* pType = NULL;
DWORD cbType = 0;
WAVEFORMATEX* pWave = NULL;
DWORD index = 0;
DWORD cEntries = 0;
DWORD dwBestRate = 0;
DWORD PacketsPerSecond = 0;
// This value is beyond the codec indexes
// and will be used to verify success.
DWORD CodecIndex = INVALID_INDEX;
// Instantiate a profile manager object.
hr = WMCreateProfileManager(&pProfileMgr);
GOTO_EXIT_IF_FAILED(hr);
// Get the codec information interface.
hr = pProfileMgr->QueryInterface(IID_IWMCodecInfo3, (void**)&pCodecInfo);
GOTO_EXIT_IF_FAILED(hr);
// Get the number of audio codecs for which there is information.
hr = pCodecInfo->GetCodecInfoCount(WMMEDIATYPE_Audio, &cEntries);
GOTO_EXIT_IF_FAILED(hr);
// Find the index of the codec corresponding to the requested subytpe.
for(index = 0; index < cEntries; index++)
{
// Get the first format for each codec.
hr = pCodecInfo->GetCodecFormat(WMMEDIATYPE_Audio, index, 0, &pStreamConfig);
GOTO_EXIT_IF_FAILED(hr);
// Get the media properties interface.
hr = pStreamConfig->QueryInterface(IID_IWMMediaProps, (void**)&pProps);
GOTO_EXIT_IF_FAILED(hr);
// Get the size required for the media type structure.
hr = pProps->GetMediaType(NULL, &cbType);
GOTO_EXIT_IF_FAILED(hr);
// Allocate memory for the media type structure.
pType = (WM_MEDIA_TYPE*) new BYTE[cbType];
if(pType == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
// Get the media type structure.
hr = pProps->GetMediaType(pType, &cbType);
GOTO_EXIT_IF_FAILED(hr);
// Check this codec against the one requested.
if(pType->subtype == SubType)
CodecIndex = index;
// The subtypes did not match. Clean up for next iteration.
SAFE_RELEASE(pStreamConfig);
SAFE_RELEASE(pProps);
SAFE_ARRAY_DELETE(pType);
// Break now if needed. Placing the break here avoids having to
// release or delete both inside and outside of the loop.
if(CodecIndex != INVALID_INDEX)
break;
} // for index
// The subtype is invalid if no codec was found that matches it.
if(CodecIndex == INVALID_INDEX)
{
hr = E_INVALIDARG;
goto Exit;
}
// Get the number of formats supported for the codec.
hr = pCodecInfo->GetCodecFormatCount(WMMEDIATYPE_Audio,
CodecIndex,
&cEntries);
GOTO_EXIT_IF_FAILED(hr);
// Loop through the formats for the codec, looking for matches.
for(index = 0; index < cEntries; index++)
{
// Get the next format.
hr = pCodecInfo->GetCodecFormat(WMMEDIATYPE_Audio,
CodecIndex,
index,
&pStreamConfig);
GOTO_EXIT_IF_FAILED(hr);
// Get the media properties interface.
hr = pStreamConfig->QueryInterface(IID_IWMMediaProps, (void**)&pProps);
GOTO_EXIT_IF_FAILED(hr);
// Get the size required for the media type structure.
hr = pProps->GetMediaType(NULL, &cbType);
GOTO_EXIT_IF_FAILED(hr);
// Allocate memory for the media type structure.
pType = (WM_MEDIA_TYPE*) new BYTE[cbType];
if(pType == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
// Get the media type structure.
hr = pProps->GetMediaType(pType, &cbType);
GOTO_EXIT_IF_FAILED(hr);
// Check that the format data is present.
if(pType->cbFormat >= sizeof(WAVEFORMATEX))
pWave = (WAVEFORMATEX*)pType->pbFormat;
else
{
// The returned media type should always have an attached
// WAVEFORMATEX structure.
hr = E_UNEXPECTED;
goto Exit;
}
// Start checking data.
// Do not check particulars unless the bit rate is in range.
if((pWave->nAvgBytesPerSec * 8) > dwBestRate &&
(pWave->nAvgBytesPerSec * 8) <= dwMaxRate)
{
// Check the limits.
if((pWave->nChannels == pWaveLimits->nChannels) &&
(pWave->wBitsPerSample == pWaveLimits->wBitsPerSample) &&
(pWave->nSamplesPerSec == pWaveLimits->nSamplesPerSec))
{
// If audio/video synchronization requested, check the number
// of packets per second (Bps / BlockAlign). The bit rate is
// greater than 3200 bps, this value must be 5.
// Otherwise this value is 3.
// This is an ASF requirement.
if(fAVSync)
{
if((pWave->nAvgBytesPerSec / pWave->nBlockAlign) >=
((pWave->nAvgBytesPerSec >= 4000) ? 5.0 : 3.0))
{
// Release the previous best match.
SAFE_RELEASE(pBestMatch);
// Set this stream configuration as the new best match.
pBestMatch = pStreamConfig;
pStreamConfig->AddRef();
// Set the best bit rate.
dwBestRate = (pWave->nAvgBytesPerSec * 8);
}
} // if fAVSync
else
{
// Release the previous best match.
SAFE_RELEASE(pBestMatch);
// Set this stream configuration as the new best match.
pBestMatch = pStreamConfig;
pStreamConfig->AddRef();
// Set the best bit rate.
dwBestRate = (pWave->nAvgBytesPerSec * 8);
} // else
} // if matching limits
} // if valid bit rate
// Clean up for next iteration.
SAFE_RELEASE(pStreamConfig);
SAFE_RELEASE(pProps);
pWave = NULL;
SAFE_ARRAY_DELETE(pType);
} // for index
// If no match was found, the arguments were not valid for the codec.
if(pBestMatch == NULL)
{
hr = E_INVALIDARG;
goto Exit;
}
// Set the pointer to the stream configuration.
*ppStreamConfig = pBestMatch;
pBestMatch = NULL;
Exit:
SAFE_RELEASE(pProfileMgr);
SAFE_RELEASE(pCodecInfo);
SAFE_RELEASE(pStreamConfig);
SAFE_RELEASE(pBestMatch);
SAFE_RELEASE(pProps);
SAFE_ARRAY_DELETE(pType);
return hr;
}
관련 항목