Tutorial: Codificando um arquivo WMA

Este tutorial mostra como usar a API transcode para codificar um arquivo WMA (Windows Media Audio).

Este tutorial reutiliza a maior parte do código do tutorial Codificando um arquivo MP4, portanto, você deve ler esse tutorial primeiro. O único código que difere é a função CreateTranscodeProfile, que cria o perfil de transcodificação.

Criar o Perfil de Transcodificação

Um perfil de transcodificação descreve os parâmetros de codificação e o contêiner de arquivos. Para o WMA, o contêiner de arquivos é um arquivo ASF (Formato Avançado de Streaming). O arquivo ASF contém um fluxo de áudio, que é codificado usando o Codificador de Áudio do Windows Media.

Para criar a topologia de transcodificação, crie o perfil de transcodificação e especifique os parâmetros para o fluxo de áudio e o contêiner. Em seguida, crie a topologia especificando a fonte de entrada, a URL de saída e o perfil de transcodificação.

Para criar o perfil, execute as etapas a seguir.

  1. Chame a função MFCreateTranscodeProfile para criar um perfil de transcodificação vazio.
  2. Chame MFTranscodeGetAudioOutputAvailableTypes para obter uma lista de tipos de mídia de áudio do codificador. Essa função retorna um ponteiro IMFCollection que representa uma coleção de ponteiros IMFMediaType .
  3. Escolha o tipo de mídia de áudio que corresponde aos requisitos de transcodificação e copie os atributos para um repositório de atributos. Para este tutorial, o primeiro tipo de mídia na lista é usado.
  4. Chame IMFTranscodeProfile::SetAudioAttributes para definir os atributos para o fluxo de áudio.
  5. Chame MFCreateAttributes para criar um repositório de atributos para os atributos no nível do contêiner.
  6. Defina o atributo MF_TRANSCODE_CONTAINERTYPE como MFTranscodeContainerType_ASF, que especifica um contêiner de arquivos ASF.
  7. Chame IMFTranscodeProfile::SetContainerAttributes para definir os atributos no nível do contêiner no perfil.
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;
}

Transcode API