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


Руководство по кодированию WMA-файла

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

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

Создание профиля Транскода

профиль транскода описывает параметры кодирования и контейнер файла. Для 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 транскодирования