媒體類型轉換

有時候,必須從 DirectShow 或 Windows Media Format SDK 在 Media Foundation 媒體類型與較舊的媒體類型結構之間進行轉換。

從格式結構到媒體基礎類型

下列函式會從格式結構初始化 Media Foundation 媒體類型。 如果資料流程或檔案標頭包含格式結構,這些函式也很有用。 例如,WAVE 音訊檔案的檔案標頭包含 WAVEATEX 結構。

要轉換的結構 函式
AM_MEDIA_TYPE (DirectShow)
DMO_MEDIA_TYPE (DirectX 媒體物件)
WM_MEDIA_TYPE (Windows Media Format SDK)
注意: 這些結構相等。
MFInitMediaTypeFromAMMediaType
BITMAPINFOHEADER MFCreateVideoMediaTypeFromBitMapInfoHeaderEx
MFVIDEOFORMAT MFInitMediaTypeFromMFVideoFormat
MPEG1VIDEOINFO MFInitMediaTypeFromMPEG1VideoInfo
MPEG2VIDEOINFO MFInitMediaTypeFromMPEG2VideoInfo
VIDEOINFOHEADER2 MFInitMediaTypeFromVideoInfoHeader2
VIDEOINFOHEADER MFInitMediaTypeFromVideoInfoHeader
其為[][供應 專案 ][XTENSIBLE] MFInitMediaTypeFromWaveFormatEx

 

從媒體基礎類型到格式結構

下列函式會從 Media Foundation 媒體類型建立或初始化格式結構。

函式 目標結構
IMFMediaType::GetRepresentation AM_MEDIA_TYPEMFVIDEOFORMATVIDEOINFOHEADERVIDEOINFOHEADER2
MFCreateAMMediaTypeFromMFMediaType AM_MEDIA_TYPE
MFCreateMFVideoFormatFromMFMediaType MFVIDEOFORMAT
MFCreateWaveFormatExFromMFMediaType 其為[][供應 專案 ][XTENSIBLE]
MFInitAMMediaTypeFromMFMediaType AM_MEDIA_TYPE

 

格式對應

下表列出對應至各種格式結構的 Media Foundation 屬性。 並非所有屬性都可以直接翻譯。 若要執行轉換,您應該使用上一節所列的函式;這些資料表主要提供供參考。

AM_MEDIA_TYPE

成員 屬性
bTemporalCompression MF_MT_ALL_SAMPLES_INDEPENDENT
bFixedSizeSamples MF_MT_FIXED_SIZE_SAMPLES
lSampleSize MF_MT_SAMPLE_SIZE

 

電壓X、波狀XTENSIBLE

成員 屬性
wFormatTag MF_MT_SUBTYPE
如果 wFormatTag 是WAVE_FORMAT_EXTENSIBLE, 則會在 SubFormat 成員中找到子類型。
nChannels MF_MT_AUDIO_NUM_CHANNELS
nSamplesPerSec MF_MT_AUDIO_SAMPLES_PER_SECOND
nAvgBytesPerSec MF_MT_AUDIO_AVG_BYTES_PER_SECOND
nBlockAlign MF_MT_AUDIO_BLOCK_ALIGNMENT
wBitsPerSample MF_MT_AUDIO_BITS_PER_SAMPLE
wValidBitsPerSample MF_MT_AUDIO_VALID_BITS_PER_SAMPLE
wSamplesPerBlock MF_MT_AUDIO_SAMPLES_PER_BLOCK
dwChannelMask MF_MT_AUDIO_CHANNEL_MASK
SubFormat MF_MT_SUBTYPE
額外的資料 MF_MT_USER_DATA

 

VIDEOINFOHEADER、VIDEOINFOHEADER2

成員 屬性
dwBitRate MF_MT_AVG_BITRATE
dwBitErrorRate MF_MT_AVG_BIT_ERROR_RATE
AvgTimePerFrame MF_MT_FRAME_RATE;使用 MFAverageTimePerFrameToFrameRate 計算此值。
dwInterlaceFlags MF_MT_INTERLACE_MODE
dwCopyProtectFlags 未定義對等專案
dwPictAspectRatioXdwPictAspectRatioY MF_MT_PIXEL_ASPECT_RATIO;必須從圖片外觀比例轉換為圖片外觀比例。
dwControlFlags MF_MT_PAD_CONTROL_FLAGS。 如果 AMCONTROL_COLORINFO_PRESENT旗標 存在,請設定擴充色彩資訊中所述的 擴充色彩屬性。
bmiHeader.biWidthbmiHeader.biHeight MF_MT_FRAME_SIZE
bmiHeader.biBitCount 在子類型中隱含 (MF_MT_SUBTYPE) 。
bmiHeader.biCompression 在子類型中隱含。
bmiHeader.biSizeImage MF_MT_SAMPLE_SIZE
調色盤資訊 MF_MT_PALETTE

 

您可以從VIDEOINFOHEADER 或 VIDEOINFOHEADER2結構推斷下列屬性,但也需要一些格式詳細資料的知識。 例如,不同的 YUV 格式有不同的步進需求。

MPEG1VIDEOINFO

成員 屬性
dwStartTimeCode MF_MT_MPEG_START_TIME_CODE
bSequenceHeader MF_MT_MPEG_SEQUENCE_HEADER
biXPelsPerMeterbiYPelsPerMeter MF_MT_PIXEL_ASPECT_RATIO

 

MPEG2VIDEOINFO

成員 屬性
dwStartTimeCode MF_MT_MPEG_START_TIME_CODE
dwSequenceHeader MF_MT_MPEG_SEQUENCE_HEADER
dwProfile MF_MT_MPEG2_PROFILE
dwLevel MF_MT_MPEG2_LEVEL
dwFlags MF_MT_MPEG2_FLAGS

 

範例

下列程式碼會從視訊媒體類型填入 BITMAPINFOHEADER 結構。 請注意,此轉換會遺失部分格式資訊, (交錯、畫面播放速率、擴充色彩資料) 。 不過,從視訊畫面儲存點陣圖時可能很有用,例如。

#include <dshow.h>
#include <dvdmedia.h>

// Converts a video type to a BITMAPINFO structure.
// The caller must free the structure by calling CoTaskMemFree.

// Note that this conversion loses some format information, including 
// interlacing, and frame rate.

HRESULT GetBitmapInfoHeaderFromMFMediaType(
    IMFMediaType *pType,            // Pointer to the media type.
    BITMAPINFOHEADER **ppBmih,      // Receives a pointer to the structure. 
    DWORD *pcbSize)                 // Receives the size of the structure.
{
    *ppBmih = NULL;
    *pcbSize = 0;

    GUID majorType = GUID_NULL;
    AM_MEDIA_TYPE *pmt = NULL;
    DWORD cbSize = 0;
    DWORD cbOffset = 0;
    BITMAPINFOHEADER *pBMIH = NULL;

    // Verify that this is a video type.
    HRESULT hr = pType->GetMajorType(&majorType);
    if (FAILED(hr))
    {
        goto done;
    }

    if (majorType != MFMediaType_Video)
    {
        hr = MF_E_INVALIDMEDIATYPE;
        goto done;
    }

    hr = pType->GetRepresentation(AM_MEDIA_TYPE_REPRESENTATION, (void**)&pmt);
    if (FAILED(hr))
    {
        goto done;
    }

    if (pmt->formattype == FORMAT_VideoInfo)
    {
        cbOffset = (FIELD_OFFSET(VIDEOINFOHEADER,bmiHeader));
    }
    else if (pmt->formattype == FORMAT_VideoInfo2)
    {
        cbOffset = (FIELD_OFFSET(VIDEOINFOHEADER2,bmiHeader));
    }
    else
    {
        hr = MF_E_INVALIDMEDIATYPE; // Unsupported format type.
        goto done;
    }

    if (pmt->cbFormat - cbOffset < sizeof(BITMAPINFOHEADER))
    {
        hr = E_UNEXPECTED; // Bad format size. 
        goto done;
    }

    cbSize = pmt->cbFormat - cbOffset;

    pBMIH = (BITMAPINFOHEADER*)CoTaskMemAlloc(cbSize);
    if (pBMIH == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto done;
    }
    
    CopyMemory(pBMIH, pmt->pbFormat + cbOffset, cbSize);
    
    *ppBmih = pBMIH;
    *pcbSize = cbSize;

done:
    if (pmt)
    {
        pType->FreeRepresentation(AM_MEDIA_TYPE_REPRESENTATION, pmt);
    }
    return hr;
}

媒體類型