教學課程:編碼 WMA 檔案
本教學課程示範如何使用 Transcode API 來編碼 Windows 媒體音訊 (WMA) 檔案。
本教學課程會重複使用 MP4 檔案編碼教學課程的大部分程式碼,因此您應該先閱讀該教學課程。 唯一不同的程式碼是 函 CreateTranscodeProfile
式 ,它會建立轉碼設定檔。
建立轉碼設定檔
轉碼設定檔描述編碼參數和檔案容器。 針對 WMA,檔案容器是 ASF) 檔案 (進階串流格式。 ASF 檔案包含使用 Windows 媒體音訊編碼器編碼的音訊資料流程。
若要建置轉碼拓撲,請建立轉碼設定檔,並指定音訊資料流程和容器的參數。 然後藉由指定輸入來源、輸出 URL 和轉碼設定檔來建立拓撲。
若要建立設定檔,請執行下列步驟。
- 呼叫 MFCreateTranscodeProfile 函式來建立空的轉碼設定檔。
- 呼叫 MFTranscodeGetAudioOutputAvailableTypes 以從編碼器取得音訊媒體類型清單。 此函式會傳回代表 IMFMediaType指標集合的IMFCollection指標。
- 選擇符合轉碼需求的音訊媒體類型,並將屬性複製到屬性存放區。 在本教學課程中,會使用清單中的第一個媒體類型。
- 呼叫 IMFCollection::GetElement 以從清單中選取音訊媒體類型。
- 查詢媒體類型,以取得媒體類型屬性存放區 之 IMFAttributes 介面的指標。
- 呼叫 IMFAttributes::GetCount 以取得媒體類型中包含的屬性數目。
- 呼叫 MFCreateAttributes 以建立新的屬性存放區。
- 呼叫 IMFAttributes::CopyAllItems ,將屬性從媒體類型複製到新的屬性存放區。
- 呼叫 IMFTranscodeProfile::SetAudioAttributes 來設定音訊資料流程的屬性。
- 呼叫 MFCreateAttributes 以建立容器層級屬性的屬性存放區。
- 將 MF_TRANSCODE_CONTAINERTYPE 屬性設定為 MFTranscodeContainerType_ASF,這個屬性會指定 ASF 檔案容器。
- 呼叫 IMFTranscodeProfile::SetContainerAttributes 以在設定檔上設定容器層級屬性。
template <class Q>
HRESULT GetCollectionObject(IMFCollection *pCollection, DWORD index, Q **ppObj)
{
IUnknown *pUnk;
HRESULT hr = pCollection->GetElement(index, &pUnk);
if (SUCCEEDED(hr))
{
hr = pUnk->QueryInterface(IID_PPV_ARGS(ppObj));
pUnk->Release();
}
return hr;
}
HRESULT CreateTranscodeProfile(IMFTranscodeProfile **ppProfile)
{
IMFTranscodeProfile *pProfile = NULL; // Transcode profile.
IMFCollection *pAvailableTypes = NULL; // List of audio media types.
IMFMediaType *pAudioType = NULL; // Audio media type.
IMFAttributes *pAudioAttrs = NULL; // Copy of the audio media type.
IMFAttributes *pContainer = NULL; // Container attributes.
DWORD dwMTCount = 0;
// Create an empty transcode profile.
HRESULT hr = MFCreateTranscodeProfile(&pProfile);
if (FAILED(hr))
{
goto done;
}
// Get output media types for the Windows Media audio encoder.
// Enumerate all codecs except for codecs with field-of-use restrictions.
// Sort the results.
DWORD dwFlags =
(MFT_ENUM_FLAG_ALL & (~MFT_ENUM_FLAG_FIELDOFUSE)) |
MFT_ENUM_FLAG_SORTANDFILTER;
hr = MFTranscodeGetAudioOutputAvailableTypes(MFAudioFormat_WMAudioV9,
dwFlags, NULL, &pAvailableTypes);
if (FAILED(hr))
{
goto done;
}
hr = pAvailableTypes->GetElementCount(&dwMTCount);
if (FAILED(hr))
{
goto done;
}
if (dwMTCount == 0)
{
hr = E_FAIL;
goto done;
}
// Get the first audio type in the collection and make a copy.
hr = GetCollectionObject(pAvailableTypes, 0, &pAudioType);
if (FAILED(hr))
{
goto done;
}
hr = MFCreateAttributes(&pAudioAttrs, 0);
if (FAILED(hr))
{
goto done;
}
hr = pAudioType->CopyAllItems(pAudioAttrs);
if (FAILED(hr))
{
goto done;
}
// Set the audio attributes on the profile.
hr = pProfile->SetAudioAttributes(pAudioAttrs);
if (FAILED(hr))
{
goto done;
}
// Set the container attributes.
hr = MFCreateAttributes(&pContainer, 1);
if (FAILED(hr))
{
goto done;
}
hr = pContainer->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_ASF);
if (FAILED(hr))
{
goto done;
}
hr = pProfile->SetContainerAttributes(pContainer);
if (FAILED(hr))
{
goto done;
}
*ppProfile = pProfile;
(*ppProfile)->AddRef();
done:
SafeRelease(&pProfile);
SafeRelease(&pAvailableTypes);
SafeRelease(&pAudioType);
SafeRelease(&pAudioAttrs);
SafeRelease(&pContainer);
return hr;
}
相關主題