使用Gstreamer 作為數(shù)據(jù)源輸出視頻數(shù)據(jù) II 媒體類(lèi)型信息

Directshow的媒體類(lèi)型結(jié)構(gòu)

在directshow中,對(duì)于push模式的source filter來(lái)說(shuō)争群,有兩個(gè)重要的基礎(chǔ)類(lèi)锨推,CSource
CSourceStream寝并。CSource是filter的基礎(chǔ)類(lèi)蜕猫,CSourceStream是outputpin的基礎(chǔ)類(lèi)寂曹。這里我們就看看后者里有關(guān)媒體類(lèi)型的內(nèi)容。
在directshow中兩個(gè)Pin(gstreamer叫做pad)相連接時(shí)回右,需要進(jìn)行類(lèi)型與格式的協(xié)商,其中就依賴(lài)CSourceStream的一個(gè)重要方法:

//Gets a media type from the output pin.
virtual HRESULT GetMediaType(
   int        iPosition,
   CMediaType *pMediaType
);

GetMediaType返回一個(gè)或多個(gè)媒體類(lèi)型(media type)漱挚,用于和下游的filter進(jìn)行協(xié)商翔烁。下游如果是decoder/encoder,需要這些信息進(jìn)行編碼和解碼工作旨涝;如果是render蹬屹,需要更詳細(xì)的信息,包括格式信息等進(jìn)行渲染。詳細(xì)可參考How to Write a Source Filter for DirectShow

AM_MEDIA_TYPE

在這里慨默,可以看到媒體類(lèi)型使用CMediaType類(lèi)來(lái)表示贩耐, CMediaType類(lèi)繼承自AM_MEDIA_TYPE結(jié)構(gòu)體,提供了AM_MEDIA_TYPE結(jié)構(gòu)體操作方法厦取。如下正式AM_MEDIA_TYPE的定義:

typedef struct _AMMediaType {
  GUID     majortype;
  GUID     subtype;
  BOOL     bFixedSizeSamples;
  BOOL     bTemporalCompression;
  ULONG    lSampleSize;
  GUID     formattype;
  IUnknown *pUnk;
  ULONG    cbFormat;
  BYTE     *pbFormat;
} AM_MEDIA_TYPE

majortype

majortype 的值是一個(gè)GUID, 用它來(lái)確定媒體數(shù)據(jù)的主要類(lèi)型潮太,directshow為每個(gè)GUID都定義了常量標(biāo)識(shí)符,下面是它的list:

GUID Description
MEDIATYPE_AnalogAudio Analog audio.模擬音頻虾攻,一般是聲卡采集輸入的數(shù)據(jù)類(lèi)型铡买,TV Audio Filter就接收這種類(lèi)型的音頻
MEDIATYPE_AnalogVideo Analog video. 模擬視頻,一般是視頻采集卡輸入的數(shù)據(jù)類(lèi)型
MEDIATYPE_Audio Audio. See Audio Subtypes. 數(shù)字音頻信號(hào)
MEDIATYPE_AUXLine21Data Line 21 data. Used by closed captions. See Line 21 Media Types. 閉路電視信號(hào)(參考EIA-608)
MEDIATYPE_File File. (Obsolete) 已經(jīng)廢棄文件類(lèi)型
MEDIATYPE_Interleaved Interleaved audio and video. Used for Digital Video (DV). DV的數(shù)據(jù)流(包括音視頻數(shù)據(jù))
MEDIATYPE_LMRT Obsolete. Do not use.
MEDIATYPE_Midi MIDI format. 樂(lè)器數(shù)字接口信號(hào)霎箍,MIDI是編曲界最廣泛的音樂(lè)標(biāo)準(zhǔn)格式
MEDIATYPE_MPEG2_PES MPEG-2 PES packets. See MPEG-2 Media Types. 用于DVD或數(shù)字視頻廣播(DVB)
MEDIATYPE_MPEG2_SECTIONS MPEG-2 section data. See MPEG-2 Media Types. MPEG-2 Demultiplexer的output媒體類(lèi)型之一
MEDIATYPE_ScriptCommand Data is a script command, used by closed captions. 閉路電視
MEDIATYPE_Stream Byte stream with no time stamps. See Stream Subtypes. 字節(jié)流奇钞,如(Pull模式)文件源的輸出數(shù)據(jù)類(lèi)型
MEDIATYPE_Text Text.
MEDIATYPE_Timecode Timecode data. Note: DirectShow does not provide any filters that support this media type.
MEDIATYPE_URL_STREAM Obsolete. Do not use.
MEDIATYPE_VBI Vertical blanking interval (VBI) data (for television). Same as KSDATAFORMAT_TYPE_VBI. 電視廣播VBI信號(hào)
MEDIATYPE_Video Video. See Video Subtypes. 數(shù)字視頻信號(hào)

參考圖:PES 在 MPEG-2 系統(tǒng)中的位置,可以看到它是一視頻編碼后更外邊的包漂坏。

image.png

subtype

很多著類(lèi)型都有子類(lèi)型景埃,在上面的列表種我們主要關(guān)心的是MEDIATYPE_Video類(lèi)型,在MEDIATYPE_Video下的subtype可以被分為幾類(lèi):

  • Analog Video Subtypes // 模擬視頻子類(lèi)型
  • DirectX Video Acceleration Video Subtypes
  • DV Video Subtypes // 攝像機(jī)DV的具體子類(lèi)型
  • H.264 Video Types // H.264類(lèi)型的video
  • Uncompressed RGB Video Subtypes
  • Video Mixing Renderer Video Subtypes //用于特定的fitler
  • YUV Video Subtypes
  • Miscellaneous Video Subtypes
  • MPEG-1,-2 media type // MPEG-1 Video數(shù)據(jù)

我們最常見(jiàn)的圖像表示方法是RGB和YUV; 在YUV視頻分類(lèi)下顶别,我們可以看到如下常用的類(lèi)型:

GUID Format Sampling Packed or planar Bits per channel
MEDIASUBTYPE_AYUV AYUV 4:4:4 Packed 8
MEDIASUBTYPE_YUY2 YUY2 4:2:2 Packed 8
MEDIASUBTYPE_UYVY UYVY 4:2:2 Packed 8
MEDIASUBTYPE_IMC1 IMC1 4:2:0 Planar 8
MEDIASUBTYPE_IMC3 IMC2 4:2:0 Planar 8
MEDIASUBTYPE_IMC2 IMC3 4:2:0 Planar 8
MEDIASUBTYPE_IMC4 IMC4 4:2:0 Planar 8
MEDIASUBTYPE_YV12 YUY2 4:2:0 Planar 8
MEDIASUBTYPE_NV12 NV12 4:2:0 Planar 8

YUV類(lèi)別下的子類(lèi)型 像素都是YUV格式纠亚, 主要按照 采樣比、存儲(chǔ)方式筋夏,和字節(jié)深度來(lái)區(qū)分蒂胞。

formattype

majortype和subtype主要描述媒體的主要類(lèi)型和次要類(lèi)型:majortype主要定義大概的分類(lèi),例如視頻条篷、音頻骗随、字節(jié)流等;子類(lèi)型定義大分類(lèi)下的更小的分類(lèi)赴叹,例如YUY2鸿染, YUY2等。
但是這些信息還不足夠保證兩個(gè)pin(gstremer稱(chēng)為pad)之間的成功連接乞巧,它們還需要一些詳細(xì)的格式信息涨椒,例如支持的圖像寬度、高度绽媒,播放頻率等蚕冬。
這些信息會(huì)被保存在一個(gè)格式數(shù)據(jù)塊,并且僅跟在AM_MEDIA_TYPE 結(jié)構(gòu)體的后面存儲(chǔ),私用AM_MEDIA_TYPE結(jié)構(gòu)體的pbFormat指針來(lái)指向是辕。這個(gè)format塊是不定長(zhǎng)的囤热,所以需要使用formattype來(lái)描述它的類(lèi)別,看它是那種媒體類(lèi)型的格式信息获三。
formattype也是使用GUID表示旁蔼,directshow同樣提供了一個(gè)常量列表來(lái)描述它所支持的Format類(lèi)型:


image.png

在上面的媒體對(duì)于視頻來(lái)說(shuō)锨苏,在常用的就是FORMAT_VideoInfo 和 FORMAT_VideoInfo2。

  • VIDEOINFOHEADER 結(jié)構(gòu)體
typedef struct tagVIDEOINFOHEADER {
  RECT             rcSource;    //確定source視頻窗口的長(zhǎng)方形
  RECT             rcTarget;    //確定目標(biāo)視頻窗口的長(zhǎng)方形
  DWORD            dwBitRate; //視頻流按bit計(jì)算的數(shù)據(jù)速率
  DWORD            dwBitErrorRate;     //出錯(cuò)率
  REFERENCE_TIME   AvgTimePerFrame;   //期望的每幀平均顯示時(shí)間棺聊,以100納秒為單位
  BITMAPINFOHEADER bmiHeader;  
} VIDEOINFOHEADER;
  • VIDEOINFOHEADER2結(jié)構(gòu)體
    VIDEOINFOHEADER2結(jié)構(gòu)體描述了用于視頻圖像的位圖信息和顏色信息伞租,包括 interlace, copy protection和 picture aspect ratio等。
typedef struct tagVIDEOINFOHEADER2 {
  RECT             rcSource;
  RECT             rcTarget;
  DWORD            dwBitRate;
  DWORD            dwBitErrorRate;
  REFERENCE_TIME   AvgTimePerFrame;
  DWORD            dwInterlaceFlags;  //flags that specify how the video is interlaced
  DWORD            dwCopyProtectFlags;  //用于copy保護(hù)
  DWORD            dwPictAspectRatioX; //The X dimension of picture aspect ratio
  DWORD            dwPictAspectRatioY; //he Y dimension of picture aspect ratio
  union {
    DWORD dwControlFlags;
    DWORD dwReserved1;
  };
  DWORD            dwReserved2;
  BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER2;
  • BITMAPINFOHEADER結(jié)構(gòu)體
    如上,在VIDEOINFOHEADER和VIDEOINFOHEADER2結(jié)構(gòu)體中又包含了一個(gè)BITMAPINFOHEADER的信息結(jié)構(gòu)體限佩,它 包含了視頻圖像的顏色和維度信息:
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize; //本結(jié)構(gòu)體大小
  LONG  biWidth;  // bitmap寬度葵诈, 單位為pixel
  LONG  biHeight; //bitmap高度, 單位為pixel
  WORD  biPlanes; //number of planes for the target device. This value must be set to 1
  WORD  biBitCount; //Specifies the number of bits per pixel (bpp)
  DWORD biCompression; //對(duì)于壓縮視頻和YUV格式犀暑,這個(gè)字段是 FOURCC code驯击,對(duì)于未壓縮的RGB格式,它又固定的值
  DWORD biSizeImage;   //image的大小耐亏,以byte為單位徊都。
  LONG  biXPelsPerMeter; //Specifies the horizontal resolution
  LONG  biYPelsPerMeter; // Specifies the vertical resolution
  DWORD biClrUsed;  // Specifies the number of color indices in the color table that are actually used by the bitmap
  DWORD biClrImportant; //Specifies the number of color indices that are considered important for displaying the bitmap.
} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

需要注意的是BITMAPINFOHEADER結(jié)構(gòu)體后面可能會(huì)跟隨palette 和 color mask信息。需要參考BITMAPINFOHEADER Color Tables的描述广辰。

rcSource暇矫,rcTarget 和biWidth/biHeight的關(guān)系

在幾個(gè)結(jié)構(gòu)體中,都有關(guān)于圖像寬度和高度的描述择吊,例如VIDEOINFOHEADER 和VIDEOINFOHEADER2 中的rcSource李根、rcTarget ;還有BITMAPINFOHEADER中的biwidth几睛、biHeight. 它們之間的關(guān)系可以用兩個(gè)filter連接后的動(dòng)作來(lái)描述:

當(dāng)filter A與Filter B 相連接后房轿,數(shù)據(jù)通過(guò)A與B之間的buffer傳遞。Buffer有自己的大小所森,它由bmiHeader.biWidth, bmiHeader.biHeight決定囱持。FilteA在填充buffer的時(shí)候,將會(huì)使用rcSource矩形來(lái)確定哪一部分的input video應(yīng)該放在buffer里焕济;并且通過(guò)拉伸操作纷妆,將由rcTarget矩形確定的buffer位置填充滿(mǎn)。
所以在填充時(shí)需要比較rcsource,bitWidth等信息晴弃,如果rcsource值為0掩幢,表示使用整個(gè)輸入視頻圖像填充;如果rctarget為0,表示填滿(mǎn)整個(gè)buffer.


gst videotestsrc 的媒體類(lèi)型信息

在gststreamer種上鞠, videotestsrc被用來(lái)生成各種格式的測(cè)試視頻數(shù)據(jù)际邻,默認(rèn)情況下,它可以無(wú)限的生成數(shù)據(jù)旗国。
**gst-launch-1.0 -v videotestsrc pattern=snow ! video/x-raw,width=1280,height=720 ! autovideosink **
例如使用如上命令產(chǎn)生的效果:

image.png

在Gststreamer中枯怖,一般用pad模板用來(lái)描述input/output pad的能力,每個(gè)filter都有一個(gè)或多個(gè)pad(directshow中稱(chēng)為PIN), 用來(lái)描述這個(gè)filter能夠接收的媒體類(lèi)型與格式或者可以輸出的媒體類(lèi)型和格式能曾。 videotestsrc作為數(shù)據(jù)生成filter度硝,它只有一個(gè)output pad, 如下是它的pad模板:

video/x-raw:
         format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }
          width: [ 1, 2147483647 ]
         height: [ 1, 2147483647 ]
      framerate: [ 0/1, 2147483647/1 ]
 multiview-mode: { (string)mono, (string)left, (string)right }
video/x-bayer:
         format: { bggr, rggb, grbg, gbrg }
          width: [ 1, 2147483647 ]
         : [ 1, 2147483647 ]
      : [ 0/1, 2147483647/1 ]
 multiview-mode: { (string)mono, (string)left, (string)right }
  • video/x-raw,video/x-bayer
    它們是兩種視頻媒體類(lèi)型寿冕。
    video/x-raw 是只未經(jīng)encode的原始視頻蕊程,video/x-bayer bayer格式的視頻
    notes: gststreamer的媒體類(lèi)型寫(xiě)法和mine一樣,但是并不能和mine對(duì)應(yīng)上驼唱,需要注意fitler的caps 模板的描述
  • format
    表示視頻支持的編碼格式藻茂。
    raw video支持的格式包含很多,可以看到對(duì)于YUV玫恳,它可以支持的格式有VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9辨赐。YUV作為標(biāo)準(zhǔn)格式,在Gststreamer和direcshow里是通用的京办。
  • width掀序,height,framerate
    寬度惭婿,高度不恭,幀速率的取值是區(qū)間值,表示可以產(chǎn)生這個(gè)范圍內(nèi)的視頻數(shù)據(jù)财饥。
  • multiview-mode
    表示在3d /VR場(chǎng)景中换吧,多畫(huà)面的顯示方式,這個(gè)不常用钥星。

CSourceStream中的GetMediaType方法

了解了directshow的媒體類(lèi)型信息沾瓦,以及gstreamer中videotestsrc的pad 模板,我們更深一步的看看如何實(shí)現(xiàn)CSourceStream的GetMediaType方法谦炒,并且他的媒體信息與videotestsrc的模板能力保持一致贯莺。
GetMediaType有兩個(gè)重載方法:

  • GetMediaType (1) 只有一個(gè)參數(shù),指向 CMediaType 類(lèi)型對(duì)象.
  • GetMediaType (2) 有兩個(gè)參數(shù)编饺,一個(gè)是index變量乖篷,一個(gè)是指向 CMediaType 類(lèi)型對(duì)象的指針.
    第一個(gè)用于只提供一個(gè)媒體類(lèi)型的場(chǎng)景,第二個(gè)用于能支持多個(gè)媒體類(lèi)型的場(chǎng)景透且,并且第二個(gè)需要和 CheckMediaType方法一起使用撕蔼。
    在CSourceStream中,已經(jīng)對(duì)這三個(gè)方法做了基本的實(shí)現(xiàn)秽誊,只需要按照自己的需要overwite相關(guān)的方法就可以鲸沮。
    我們實(shí)現(xiàn)比較簡(jiǎn)單的方法1,只包含一個(gè)參數(shù):
HRESULT CVCamStream::GetMediaType(CMediaType *pmt)
{
  //為pmt創(chuàng)建一個(gè)VIDEOINFOHEADER結(jié)構(gòu)體指針锅论,并為它分配內(nèi)存
    DECLARE_PTR(VIDEOINFOHEADER, pvi, 
    pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
    ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));

    pvi->bmiHeader.biWidth = 1280; //圖像寬度
    pvi->bmiHeader.biHeight = 720;  //圖像高度
    pvi->AvgTimePerFrame = 333333;//每幀平均顯示時(shí)常,單位100-nanosecond
    pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');//對(duì)于YUV格式需要在這個(gè)字段設(shè)置它的4CC代碼
    pvi->bmiHeader.biBitCount = 16; //設(shè)置YUY2格式下一個(gè)像素的bits數(shù)
    pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);//bmiHeader的size
    pvi->bmiHeader.biPlanes = 1; //總是設(shè)置1
    pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth * 
        pvi->bmiHeader.biHeight * 2;//YUY2一個(gè)像素相當(dāng)于兩個(gè)字節(jié)讼溺,設(shè)置圖像的大小,單位是字節(jié)byte.
    pvi->bmiHeader.biClrImportant = 0; //0表示所有顏色都是重要的

    SetRectEmpty(&(pvi->rcSource)); //填充所有source image數(shù)據(jù)
    SetRectEmpty(&(pvi->rcTarget));  //填充滿(mǎn)buffer

    pmt->SetType(&MEDIATYPE_Video);  //設(shè)置著類(lèi)型未video 對(duì)應(yīng)video/x-raw
    pmt->SetFormatType(&FORMAT_VideoInfo); //設(shè)置格式類(lèi)型為FORMAT_VideoInfo
    pmt->SetTemporalCompression(FALSE);  // 每一幀無(wú)壓縮
    pmt->SetSubtype(&MEDIASUBTYPE_YUY2); //設(shè)置子類(lèi)型格式
    pmt->SetSampleSize(pvi->bmiHeader.biSizeImage);//設(shè)置sample的大小為固定1幀的大小
    return NOERROR;

} 

如上directshow的代碼最易,在gstreamer中怒坯,它對(duì)應(yīng)的videotestsrc的caps信息為:
video/x-raw,width=1280,height=720炫狱,format=YUY2,framerate=(fraction)30/1
這里需要注意剔猿,framerate的格式用的是我們通常理解的幀/每秒视译, pvi->AvgTimePerFrame用的是時(shí)間,單位是100-nanosecond归敬。
可以使用gst-launch-1.0測(cè)試以下:

gst-launch-1.0 -v videotestsrc \
         ! video/x-raw,foramt=YUV2,width=1280,height=720,framerate=30/1 \
        !  autovideosink

顯示效果:


image.png

CSourceStream中的DecideBufferSize方法

當(dāng)確定了媒體類(lèi)型和格式信息后酷含,作為通常output pin還需要overwiter DecideBufferSize方法,這個(gè)方法用來(lái)設(shè)置sample buffers的大小

HRESULT CVCamStream::DecideBufferSize(IMemAllocator *pAlloc, //pAlloc為指向allocator的指針汪茧,allocator管理這buffer
    ALLOCATOR_PROPERTIES *pProperties)//ALLOCATOR_PROPERTIES 包含有input pin對(duì)buffer的需求
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());
    HRESULT hr = NOERROR;

    VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)m_mt.Format();
    pProperties->cBuffers = 1;  //設(shè)置被allocator創(chuàng)建的buffer的多少
    pProperties->cbBuffer = pvi->bmiHeader.biSizeImage; //設(shè)置buffer的大小椅亚,以字節(jié)為單位

    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProperties, &Actual);//這是新屬性

    if (FAILED(hr)) return hr;
    if (Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;

    return NOERROR;
}

如上面的方法,allocator被要求只創(chuàng)建一個(gè)buffer舱污,且大小等于1幀(bitmap的大醒教颉)。

IAMStreamConfig接口和video Capabilities

始于視頻輸入設(shè)備來(lái)說(shuō)慌闭,它們通常支持一些列的格式别威。例如一個(gè)設(shè)備可能會(huì)支持 16-bit RGB, 32-bit RGB, 和YUYV. 在每個(gè)格式里,這個(gè)設(shè)備又可能會(huì)支持一系列的幀大小.
這時(shí)候 IAMStreamConfig接口通常被用來(lái)報(bào)告這個(gè)設(shè)備支持的所有格式信息驴剔,并且允許設(shè)置格式信息, 對(duì)于capture filter來(lái)說(shuō)省古,它的output pin需要實(shí)現(xiàn)這個(gè)接口。

HRESULT GetNumberOfCapabilities(
  [out] int *piCount,
  [out] int *piSize
);

這個(gè)接口返回兩個(gè)數(shù)據(jù): 通過(guò)piCount獲得這個(gè)filter支持的媒體類(lèi)型個(gè)數(shù)丧失。通過(guò)piSize可以獲得保存caps信息的結(jié)構(gòu)體的大小豺妓,對(duì)于視頻來(lái)說(shuō),這個(gè)接口體時(shí)VIDEO_STREAM_CONFIG_CAPS布讹。

HRESULT GetStreamCaps(
  [in]  int           iIndex,
  [out] AM_MEDIA_TYPE **ppmt,
  [out] BYTE          *pSCC
);

這個(gè)方法通過(guò)索引index獲得具體的某個(gè)format信息(ppmt指向)和能力信息(pSCC指向)琳拭,對(duì)于視頻pSCC指向一個(gè) VIDEO_STREAM_CONFIG_CAPS結(jié)構(gòu)體。

  • SetFormatGetFormat
    GetFormat用于返回一個(gè)pin的format信息:當(dāng)pin已經(jīng)連接成功描验,它返回的是當(dāng)前正在使用的format白嘁;如果還沒(méi)有連接成功,它返回下次連接最合適的format. 特別是如果用戶(hù)使用了setFormat 設(shè)置了一個(gè)format, 則GetFormat會(huì)返回這個(gè)設(shè)置的值膘流。
    setformat可以用來(lái)設(shè)置output pin的格式絮缅,如果還沒(méi)有連接了,這個(gè)format將被用來(lái)做下一次連接呼股,如果已經(jīng)連接了. 這個(gè)方法會(huì)嘗試重連接耕魄。
  • VIDEO_STREAM_CONFIG_CAPS
    這個(gè)結(jié)構(gòu)體用來(lái)描述設(shè)備的視頻能力,包括format和resolution信息:
typedef struct _VIDEO_STREAM_CONFIG_CAPS {
  GUID     guid;   //確定Format類(lèi)型的GUID
  ULONG    VideoStandard;//支持的模擬視頻標(biāo)準(zhǔn)彭谁,數(shù)字視頻設(shè)為0(AnalogVideo_None)
  SIZE     InputSize;  ////輸入視頻的大小    ---已經(jīng)廢棄
  SIZE     MinCroppingSize; //允許的最小resSource   ---已經(jīng)廢棄
  SIZE     MaxCroppingSize; //允許的最小resSource   ---已經(jīng)廢棄
  int      CropGranularityX;   //resSource的水平increment的度   ---已經(jīng)廢棄
  int      CropGranularityY;   //resSource的垂直increment的度    ---已經(jīng)廢棄
  int      CropAlignX;      //resSource水平對(duì)齊  ---已經(jīng)廢棄
  int      CropAlignY;       //resSource垂直對(duì)齊   ---已經(jīng)廢棄
  SIZE     MinOutputSize;   //最小輸出大小   ---已經(jīng)廢棄
  SIZE     MaxOutputSize;   //最大輸出大小  ---已經(jīng)廢棄
  int      OutputGranularityX;  //Granularity of the output width  ---已經(jīng)廢棄
  int      OutputGranularityY;  //Granularity of output height.  ---已經(jīng)廢棄
  int      StretchTapsX;     //水平stretch的程度   取值[0,1,2,3...] ---已經(jīng)廢棄   
  int      StretchTapsY;      //垂直stretch的程度    ---已經(jīng)廢棄
  int      ShrinkTapsX;    //水平Shrink的程度      ---已經(jīng)廢棄
  int      ShrinkTapsY;     //水平Shrink的程度     ---已經(jīng)廢棄
  LONGLONG MinFrameInterval;   //最小幀間隔 單位100納秒
  LONGLONG MaxFrameInterval;  //最大幀間隔   單位100納秒
  LONG     MinBitsPerSecond;   //Minimum data rate this pin can produce. ---已經(jīng)廢棄
  LONG     MaxBitsPerSecond;  //Maximum data rate this pin can produce. ---已經(jīng)廢棄
} VIDEO_STREAM_CONFIG_CAPS;

IAMStreamConfig::GetStreamCaps將返回這個(gè)結(jié)構(gòu)體吸奴,應(yīng)用程序可以使用這個(gè)信息output pin的格式。關(guān)于它詳細(xì)的介紹可以參考Video CapabilitiesVIDEO_STREAM_CONFIG_CAPS structure。例如對(duì)于如下的設(shè)置:
MinOutputSize: 160 x 120
MaxOutputSize: 320 x 240
OutputGranularityX: 8 pixels (horizontal step size)
OutputGranularityY: 8 pixels (vertical step size)
下圖是這些屬性值的解釋?zhuān)?br>

image.png

最后我們來(lái)看一下则奥,根據(jù)我們的媒體和格式類(lèi)型考润,實(shí)現(xiàn)GetStreamCaps方法:

HRESULT STDMETHODCALLTYPE CVCamStream::GetStreamCaps(int iIndex, 
    AM_MEDIA_TYPE **pmt, BYTE *pSCC)
{
    if (iIndex < 0 )
        return E_INVALIDARG;

    *pmt = CreateMediaType(&m_mt); //創(chuàng)建媒體類(lèi)型
    DECLARE_PTR(VIDEOINFOHEADER, pvi, (*pmt)->pbFormat); //創(chuàng)建format類(lèi)型

        //設(shè)置format
    pvi->bmiHeader.biWidth = 1280; 
    pvi->bmiHeader.biHeight = 720;
    pvi->AvgTimePerFrame = 333333;
    pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
    pvi->bmiHeader.biBitCount = 16;
    pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pvi->bmiHeader.biPlanes = 1;
    pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth * 
        pvi->bmiHeader.biHeight * 2;
    pvi->bmiHeader.biClrImportant = 0;

    SetRectEmpty(&(pvi->rcSource)); 
    SetRectEmpty(&(pvi->rcTarget)); 
         //設(shè)置meida Type
    (*pmt)->majortype = MEDIATYPE_Video;
    (*pmt)->subtype = MEDIASUBTYPE_YUY2;
    (*pmt)->formattype = FORMAT_VideoInfo;
    (*pmt)->bTemporalCompression = FALSE;
    (*pmt)->bFixedSizeSamples = FALSE;
    (*pmt)->lSampleSize = pvi->bmiHeader.biSizeImage;
    (*pmt)->cbFormat = sizeof(VIDEOINFOHEADER);
       //創(chuàng)建VIDEO_STREAM_CONFIG_CAPS結(jié)構(gòu)體
    DECLARE_PTR(VIDEO_STREAM_CONFIG_CAPS, pvscc, pSCC);
       //設(shè)置VIDEO_STREAM_CONFIG_CAPS
    pvscc->guid = FORMAT_VideoInfo;  //媒體類(lèi)型為FORMAT_VideoInfo
    pvscc->VideoStandard = AnalogVideo_None;  //不是模擬視頻
    pvscc->InputSize.cx = pvi->bmiHeader.biWidth;  //輸入寬度
    pvscc->InputSize.cy = pvi->bmiHeader.biHeight; //輸入高度
    pvscc->MinCroppingSize.cx = pvi->bmiHeader.biWidth;  //最小可裁剪寬度 相當(dāng)于不允許水平裁剪
    pvscc->MinCroppingSize.cy = pvi->bmiHeader.biHeight;//最小可裁剪高度
    pvscc->MaxCroppingSize.cx = pvi->bmiHeader.biWidth;//最大可裁剪寬度
    pvscc->MaxCroppingSize.cy = pvi->bmiHeader.biHeight;//最大可裁剪高度
    pvscc->CropGranularityX = pvi->bmiHeader.biWidth;  //水平裁剪增量
    pvscc->CropGranularityY = pvi->bmiHeader.biHeight; //水平裁剪增量
    pvscc->CropAlignX = 0;  //水平對(duì)其
    pvscc->CropAlignY = 0;  //垂直對(duì)齊

    pvscc->MinOutputSize.cx = pvi->bmiHeader.biWidth;   //最小輸出寬度
    pvscc->MinOutputSize.cy = pvi->bmiHeader.biHeight;   //最小輸出高度度
    pvscc->MaxOutputSize.cx = pvi->bmiHeader.biWidth;  /最大輸出寬度
    pvscc->MaxOutputSize.cy = pvi->bmiHeader.biHeight;  //最大輸出高度度
    pvscc->OutputGranularityX = 0;  //水平輸出變化增量
    pvscc->OutputGranularityY = 0;  //垂直輸出變化增量
    pvscc->StretchTapsX = 0;   //不允許tretching
    pvscc->StretchTapsY = 0;    //不允許tretching
    pvscc->ShrinkTapsX = 0;     //不允許Shrink
    pvscc->ShrinkTapsY = 0;     //不允許Shrink
    pvscc->MinFrameInterval = pvi->AvgTimePerFrame;   //最小幀間隔=平均幀播放時(shí)間
    pvscc->MaxFrameInterval = pvi->AvgTimePerFrame; //最大幀間隔=平均幀播放時(shí)間
    pvscc->MinBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight 
        * 2 * 8 * (10000000 / pvi->AvgTimePerFrame);  //最小輸出數(shù)據(jù)bit單位
    pvscc->MaxBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight 
        * 2 * 8 * (10000000 / pvi->AvgTimePerFrame); /最大輸出數(shù)據(jù)bit單位

    return S_OK;
}

上面有一個(gè)關(guān)于pin產(chǎn)生數(shù)據(jù)大小的計(jì)算:
pvscc->MinBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight
* 2 * 8 * (10000000 / pvi->AvgTimePerFrame);
biWidth 是位圖寬度(單位像素),biHeight是位圖高度(單位像素)逞度,YUV2一個(gè)像素需要2個(gè)字節(jié)额划,每個(gè)字節(jié)8bit位妙啃。所以biWidth biHeight28就是bitmap的大小档泽。10000000 / pvi->AvgTimePerFrame表示一秒中,可以播放多少幀揖赴。我們知道這個(gè)值在我們的例子里就是30.
所以最終我們獲得了馆匿,每秒鐘output pin可以傳輸?shù)腷it的大小。他就等于size(bitmap)
幀頻率燥滑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末渐北,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铭拧,更是在濱河造成了極大的恐慌赃蛛,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搀菩,死亡現(xiàn)場(chǎng)離奇詭異呕臂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)肪跋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)歧蒋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人州既,你說(shuō)我怎么就攤上這事谜洽。” “怎么了吴叶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵阐虚,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蚌卤,道長(zhǎng)实束,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任造寝,我火速辦了婚禮磕洪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诫龙。我一直安慰自己析显,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布签赃。 她就那樣靜靜地躺著谷异,像睡著了一般分尸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歹嘹,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天箩绍,我揣著相機(jī)與錄音,去河邊找鬼尺上。 笑死材蛛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的怎抛。 我是一名探鬼主播卑吭,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼马绝!你這毒婦竟也來(lái)了豆赏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤富稻,失蹤者是張志新(化名)和其女友劉穎掷邦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體椭赋,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抚岗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纹份。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苟跪。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蔓涧,靈堂內(nèi)的尸體忽然破棺而出件已,到底是詐尸還是另有隱情,我是刑警寧澤元暴,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布篷扩,位于F島的核電站,受9級(jí)特大地震影響茉盏,放射性物質(zhì)發(fā)生泄漏鉴未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一鸠姨、第九天 我趴在偏房一處隱蔽的房頂上張望铜秆。 院中可真熱鬧,春花似錦讶迁、人聲如沸连茧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啸驯。三九已至客扎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罚斗,已是汗流浹背徙鱼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留针姿,地道東北人袱吆。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像搓幌,于是被迫代替她去往敵國(guó)和親杆故。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 今天青石的票圈出鏡率最高的堂污,莫過(guò)于張藝謀的新片終于定檔了。 一張滿(mǎn)溢著水墨風(fēng)的海報(bào)一次次的出現(xiàn)在票圈里龄砰,也就是老謀...
    青石電影閱讀 10,309評(píng)論 1 2
  • 一盟猖、jQuery簡(jiǎn)介 JQ是JS的一個(gè)優(yōu)秀的庫(kù),大型開(kāi)發(fā)必備换棚。在此式镐,我想說(shuō)的是,JQ里面很多函數(shù)使用和JS類(lèi)似固蚤,所...
    Welkin_qing閱讀 12,281評(píng)論 1 6
  • 字符串 1.什么是字符串 使用單引號(hào)或者雙引號(hào)括起來(lái)的字符集就是字符串娘汞。 引號(hào)中單獨(dú)的符號(hào)、數(shù)字夕玩、字母等叫字符你弦。 ...
    mango_2e17閱讀 7,495評(píng)論 1 7
  • 一場(chǎng)說(shuō)走就走的旅行。 簡(jiǎn)單地整理幾件必備旅行用品燎孟,7.18日早上8.00準(zhǔn)時(shí)出發(fā)了禽作,計(jì)劃一路南下然后繞西南一圈回恩...
    悠游魚(yú)閱讀 3,454評(píng)論 3 6
  • 原來(lái)看過(guò)一段話(huà),第一厲害的人有能力沒(méi)脾氣揩页,第二厲害的人有能力有脾氣旷偿,最差的是沒(méi)能力有脾氣的人。 以我最...
    涼風(fēng)豆豆閱讀 1,543評(píng)論 2 0