Tutorial: Codieren einer WMA-Datei

In diesem Tutorial wird gezeigt, wie Sie die Transcodierungs-API verwenden, um eine WMA-Datei (Windows Media Audio) zu codieren.

In diesem Tutorial wird der meiste Code aus dem Tutorial Codierung einer MP4-Datei wiederverwendet. Daher sollten Sie dieses Tutorial zuerst lesen. Der einzige Code, der sich unterscheidet, ist die Funktion CreateTranscodeProfile, die das Transcodierungsprofil erstellt.

Erstellen des Transcodierungsprofils

Ein Transcodierungsprofil beschreibt die Codierungsparameter und den Dateicontainer. Für WMA ist der Dateicontainer eine ASF-Datei (Advanced Streaming Format). Die ASF-Datei enthält einen Audiostream, der mit dem Windows Media Audio Encoder codiert wird.

Um die Transcodierungstopologie zu erstellen, erstellen Sie das Transcodierungsprofil, und geben Sie die Parameter für den Audiostream und den Container an. Erstellen Sie dann die Topologie, indem Sie die Eingabequelle, die Ausgabe-URL und das Transcodierungsprofil angeben.

Führen Sie zum Erstellen des Profils die folgenden Schritte aus.

  1. Rufen Sie die MFCreateTranscodeProfile-Funktion auf, um ein leeres Transcodierungsprofil zu erstellen.
  2. Rufen Sie MFTranscodeGetAudioOutputAvailableTypes auf , um eine Liste der Audiomedientypen vom Encoder abzurufen. Diese Funktion gibt einen IMFCollection-Zeiger zurück, der eine Auflistung von IMFMediaType-Zeigern darstellt.
  3. Wählen Sie den Audiomedientyp aus, der Ihren Transcodierungsanforderungen entspricht, und kopieren Sie die Attribute in einen Attributspeicher. In diesem Tutorial wird der erste Medientyp in der Liste verwendet.
  4. Rufen Sie IMFTranscodeProfile::SetAudioAttributes auf, um die Attribute für den Audiostream festzulegen.
  5. Rufen Sie MFCreateAttributes auf, um einen Attributspeicher für die Attribute auf Containerebene zu erstellen.
  6. Legen Sie das attribut MF_TRANSCODE_CONTAINERTYPE auf MFTranscodeContainerType_ASF fest, das einen ASF-Dateicontainer angibt.
  7. Rufen Sie IMFTranscodeProfile::SetContainerAttributes auf, um die Attribute auf Containerebene für das Profil festzulegen.
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;
}

Transcodierungs-API