Bagikan melalui


Tutorial: Mengodekan File WMA

Tutorial ini menunjukkan cara menggunakan API Transcode untuk mengodekan file Windows Media Audio (WMA).

Tutorial ini menggunakan kembali sebagian besar kode dari tutorial Pengodean File MP4, jadi Anda harus membaca tutorial itu terlebih dahulu. Satu-satunya kode yang berbeda adalah fungsi CreateTranscodeProfile, yang membuat profil transkode.

Membuat Profil Transcode

Profil transkode menjelaskan parameter pengodean dan kontainer file. Untuk WMA, kontainer file adalah file Advanced Streaming Format (ASF). File ASF berisi aliran audio, yang dikodekan menggunakan Windows Media Audio Encoder.

Untuk membangun topologi transkode, buat profil transkode dan tentukan parameter untuk aliran audio dan kontainer. Kemudian buat topologi dengan menentukan sumber input, URL output, dan profil transkode.

Untuk membuat profil, lakukan langkah-langkah berikut.

  1. Panggil fungsi MFCreateTranscodeProfile untuk membuat profil transkode kosong.
  2. Panggil MFTranscodeGetAudioOutputAvailableTypes untuk mendapatkan daftar jenis media audio dari encoder. Fungsi ini mengembalikan penunjuk IMFCollection yang mewakili kumpulan pointer IMFMediaType .
  3. Pilih jenis media audio yang cocok dengan persyaratan transcoding Anda dan salin atribut ke penyimpanan atribut. Untuk tutorial ini, jenis media pertama dalam daftar digunakan.
  4. Panggil IMFTranscodeProfile::SetAudioAttributes untuk mengatur atribut untuk aliran audio.
  5. Panggil MFCreateAttributes untuk membuat penyimpanan atribut untuk atribut tingkat kontainer.
  6. Atur atribut MF_TRANSCODE_CONTAINERTYPE ke MFTranscodeContainerType_ASF, yang menentukan kontainer file ASF.
  7. Panggil IMFTranscodeProfile::SetContainerAttributes untuk mengatur atribut tingkat kontainer pada profil.
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;
}

API Transkode