Поделиться через


Руководство. Кодирование WMA-файла

В этом руководстве показано, как использовать API перекодировки для кодирования файла Windows Media Audio (WMA).

В этом руководстве повторно используется большая часть кода из учебника Кодирование MP4-файла, поэтому сначала следует прочитать этот учебник. Единственным отличием кода является функция CreateTranscodeProfile, которая создает профиль перекодирования.

Создание профиля transcode

Профиль перекодирования описывает параметры кодирования и контейнер файлов. Для WMA контейнер файлов является файлом расширенного формата потоковой передачи (ASF). ASF-файл содержит аудиопоток, который закодирован с помощью кодировщика звука Windows Media.

Чтобы создать топологию перекодировки, создайте профиль перекодировки и укажите параметры для аудиопотока и контейнера. Затем создайте топологию, указав источник входных данных, URL-адрес выходных данных и профиль перекодирования.

Чтобы создать профиль, выполните следующие действия.

  1. Вызовите функцию MFCreateTranscodeProfile , чтобы создать пустой профиль перекодирования.
  2. Вызовите MFTranscodeGetAudioOutputAvailableTypes , чтобы получить список типов аудиоданных из кодировщика. Эта функция возвращает указатель IMFCollection , представляющий коллекцию указателей IMFMediaType .
  3. Выберите тип звукового носителя, соответствующий вашим требованиям к перекодирования, и скопируйте атрибуты в хранилище атрибутов. В этом руководстве используется первый тип мультимедиа в списке.
    • Вызовите IMFCollection::GetElement , чтобы выбрать тип звукового носителя из списка.
    • Запросите тип носителя, чтобы получить указатель на интерфейс IMFAttributes хранилища атрибутов типа мультимедиа.
    • Вызовите IMFAttributes::GetCount , чтобы получить количество атрибутов, содержащихся в типе мультимедиа.
    • Вызовите MFCreateAttributes , чтобы создать новое хранилище атрибутов.
    • Вызовите IMFAttributes::CopyAllItems , чтобы скопировать атрибуты из типа носителя в новое хранилище атрибутов.
  4. Вызовите IMFTranscodeProfile::SetAudioAttributes , чтобы задать атрибуты для звукового потока.
  5. Вызовите MFCreateAttributes , чтобы создать хранилище атрибутов для атрибутов уровня контейнера.
  6. Задайте для атрибута MF_TRANSCODE_CONTAINERTYPEзначение MFTranscodeContainerType_ASF, указывающее контейнер файлов ASF.
  7. Вызовите 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;
}

API перекодировки