Directshow的媒体类型结构
在directshow中,对于push模式的source filter来说,有两个重要的基础类,CSource
和CSourceStream。CSource是filter的基础类,CSourceStream是outputpin的基础类。这里我们就看看后者里有关媒体类型的内容。
在directshow中两个Pin(gstreamer叫做pad)相连接时,需要进行类型与格式的协商,其中就依赖CSourceStream的一个重要方法:
//Gets a media type from the output pin.
virtual HRESULT GetMediaType(
int iPosition,
CMediaType *pMediaType
);
GetMediaType返回一个或多个媒体类型(media type),用于和下游的filter进行协商。下游如果是decoder/encoder,需要这些信息进行编码和解码工作;如果是render,需要更详细的信息,包括格式信息等进行渲染。详细可参考How to Write a Source Filter for DirectShow
AM_MEDIA_TYPE
在这里,可以看到媒体类型使用CMediaType类来表示, CMediaType类继承自AM_MEDIA_TYPE结构体,提供了AM_MEDIA_TYPE结构体操作方法。如下正式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 的值是一个GUID, 用它来确定媒体数据的主要类型,directshow为每个GUID都定义了常量标识符,下面是它的list:
GUID | Description |
---|---|
MEDIATYPE_AnalogAudio | Analog audio.模拟音频,一般是声卡采集输入的数据类型,TV Audio Filter就接收这种类型的音频 |
MEDIATYPE_AnalogVideo | Analog video. 模拟视频,一般是视频采集卡输入的数据类型 |
MEDIATYPE_Audio | Audio. See Audio Subtypes. 数字音频信号 |
MEDIATYPE_AUXLine21Data | Line 21 data. Used by closed captions. See Line 21 Media Types. 闭路电视信号(参考EIA-608) |
MEDIATYPE_File | File. (Obsolete) 已经废弃文件类型 |
MEDIATYPE_Interleaved | Interleaved audio and video. Used for Digital Video (DV). DV的数据流(包括音视频数据) |
MEDIATYPE_LMRT | Obsolete. Do not use. |
MEDIATYPE_Midi | MIDI format. 乐器数字接口信号,MIDI是编曲界最广泛的音乐标准格式 |
MEDIATYPE_MPEG2_PES | MPEG-2 PES packets. See MPEG-2 Media Types. 用于DVD或数字视频广播(DVB) |
MEDIATYPE_MPEG2_SECTIONS | MPEG-2 section data. See MPEG-2 Media Types. MPEG-2 Demultiplexer的output媒体类型之一 |
MEDIATYPE_ScriptCommand | Data is a script command, used by closed captions. 闭路电视 |
MEDIATYPE_Stream | Byte stream with no time stamps. See Stream Subtypes. 字节流,如(Pull模式)文件源的输出数据类型 |
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信号 |
MEDIATYPE_Video | Video. See Video Subtypes. 数字视频信号 |
参考图:PES 在 MPEG-2 系统中的位置,可以看到它是一视频编码后更外边的包。
subtype
很多著类型都有子类型,在上面的列表种我们主要关心的是MEDIATYPE_Video类型,在MEDIATYPE_Video下的subtype可以被分为几类:
- Analog Video Subtypes // 模拟视频子类型
- DirectX Video Acceleration Video Subtypes
- DV Video Subtypes // 摄像机DV的具体子类型
- H.264 Video Types // H.264类型的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数据
我们最常见的图像表示方法是RGB和YUV; 在YUV视频分类下,我们可以看到如下常用的类型:
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类别下的子类型 像素都是YUV格式, 主要按照 采样比、存储方式,和字节深度来区分。
formattype
majortype和subtype主要描述媒体的主要类型和次要类型:majortype主要定义大概的分类,例如视频、音频、字节流等;子类型定义大分类下的更小的分类,例如YUY2, YUY2等。
但是这些信息还不足够保证两个pin(gstremer称为pad)之间的成功连接,它们还需要一些详细的格式信息,例如支持的图像宽度、高度,播放频率等。
这些信息会被保存在一个格式数据块,并且仅跟在AM_MEDIA_TYPE 结构体的后面存储,私用AM_MEDIA_TYPE结构体的pbFormat指针来指向。这个format块是不定长的,所以需要使用formattype来描述它的类别,看它是那种媒体类型的格式信息。
formattype也是使用GUID表示,directshow同样提供了一个常量列表来描述它所支持的Format类型:
在上面的媒体对于视频来说,在常用的就是FORMAT_VideoInfo 和 FORMAT_VideoInfo2。
- VIDEOINFOHEADER 结构体
typedef struct tagVIDEOINFOHEADER {
RECT rcSource; //确定source视频窗口的长方形
RECT rcTarget; //确定目标视频窗口的长方形
DWORD dwBitRate; //视频流按bit计算的数据速率
DWORD dwBitErrorRate; //出错率
REFERENCE_TIME AvgTimePerFrame; //期望的每帧平均显示时间,以100纳秒为单位
BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
- VIDEOINFOHEADER2结构体
VIDEOINFOHEADER2结构体描述了用于视频图像的位图信息和颜色信息,包括 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保护
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结构体
如上,在VIDEOINFOHEADER和VIDEOINFOHEADER2结构体中又包含了一个BITMAPINFOHEADER的信息结构体,它 包含了视频图像的颜色和维度信息:
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; //本结构体大小
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; //对于压缩视频和YUV格式,这个字段是 FOURCC code,对于未压缩的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结构体后面可能会跟随palette 和 color mask信息。需要参考BITMAPINFOHEADER Color Tables的描述。
rcSource,rcTarget 和biWidth/biHeight的关系
在几个结构体中,都有关于图像宽度和高度的描述,例如VIDEOINFOHEADER 和VIDEOINFOHEADER2 中的rcSource、rcTarget ;还有BITMAPINFOHEADER中的biwidth、biHeight. 它们之间的关系可以用两个filter连接后的动作来描述:
当filter A与Filter B 相连接后,数据通过A与B之间的buffer传递。Buffer有自己的大小,它由bmiHeader.biWidth, bmiHeader.biHeight决定。FilteA在填充buffer的时候,将会使用rcSource矩形来确定哪一部分的input video应该放在buffer里;并且通过拉伸操作,将由rcTarget矩形确定的buffer位置填充满。
所以在填充时需要比较rcsource,bitWidth等信息,如果rcsource值为0,表示使用整个输入视频图像填充;如果rctarget为0,表示填满整个buffer.
gst videotestsrc 的媒体类型信息
在gststreamer种, videotestsrc被用来生成各种格式的测试视频数据,默认情况下,它可以无限的生成数据。
**gst-launch-1.0 -v videotestsrc pattern=snow ! video/x-raw,width=1280,height=720 ! autovideosink **
例如使用如上命令产生的效果:
在Gststreamer中,一般用pad模板用来描述input/output pad的能力,每个filter都有一个或多个pad(directshow中称为PIN), 用来描述这个filter能够接收的媒体类型与格式或者可以输出的媒体类型和格式。 videotestsrc作为数据生成filter,它只有一个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
它们是两种视频媒体类型。
video/x-raw 是只未经encode的原始视频,video/x-bayer bayer格式的视频
notes: gststreamer的媒体类型写法和mine一样,但是并不能和mine对应上,需要注意fitler的caps 模板的描述 - format
表示视频支持的编码格式。
raw video支持的格式包含很多,可以看到对于YUV,它可以支持的格式有VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9。YUV作为标准格式,在Gststreamer和direcshow里是通用的。 - width,height,framerate
宽度,高度,帧速率的取值是区间值,表示可以产生这个范围内的视频数据。 - multiview-mode
表示在3d /VR场景中,多画面的显示方式,这个不常用。
CSourceStream中的GetMediaType方法
了解了directshow的媒体类型信息,以及gstreamer中videotestsrc的pad 模板,我们更深一步的看看如何实现CSourceStream的GetMediaType方法,并且他的媒体信息与videotestsrc的模板能力保持一致。
GetMediaType有两个重载方法:
- GetMediaType (1) 只有一个参数,指向 CMediaType 类型对象.
- GetMediaType (2) 有两个参数,一个是index变量,一个是指向 CMediaType 类型对象的指针.
第一个用于只提供一个媒体类型的场景,第二个用于能支持多个媒体类型的场景,并且第二个需要和 CheckMediaType方法一起使用。
在CSourceStream中,已经对这三个方法做了基本的实现,只需要按照自己的需要overwite相关的方法就可以。
我们实现比较简单的方法1,只包含一个参数:
HRESULT CVCamStream::GetMediaType(CMediaType *pmt)
{
//为pmt创建一个VIDEOINFOHEADER结构体指针,并为它分配内存
DECLARE_PTR(VIDEOINFOHEADER, pvi,
pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));
pvi->bmiHeader.biWidth = 1280; //图像宽度
pvi->bmiHeader.biHeight = 720; //图像高度
pvi->AvgTimePerFrame = 333333;//每帧平均显示时常,单位100-nanosecond
pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');//对于YUV格式需要在这个字段设置它的4CC代码
pvi->bmiHeader.biBitCount = 16; //设置YUY2格式下一个像素的bits数
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);//bmiHeader的size
pvi->bmiHeader.biPlanes = 1; //总是设置1
pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth *
pvi->bmiHeader.biHeight * 2;//YUY2一个像素相当于两个字节,设置图像的大小,单位是字节byte.
pvi->bmiHeader.biClrImportant = 0; //0表示所有颜色都是重要的
SetRectEmpty(&(pvi->rcSource)); //填充所有source image数据
SetRectEmpty(&(pvi->rcTarget)); //填充满buffer
pmt->SetType(&MEDIATYPE_Video); //设置著类型未video 对应video/x-raw
pmt->SetFormatType(&FORMAT_VideoInfo); //设置格式类型为FORMAT_VideoInfo
pmt->SetTemporalCompression(FALSE); // 每一帧无压缩
pmt->SetSubtype(&MEDIASUBTYPE_YUY2); //设置子类型格式
pmt->SetSampleSize(pvi->bmiHeader.biSizeImage);//设置sample的大小为固定1帧的大小
return NOERROR;
}
如上directshow的代码,在gstreamer中,它对应的videotestsrc的caps信息为:
video/x-raw,width=1280,height=720,format=YUY2,framerate=(fraction)30/1
这里需要注意,framerate的格式用的是我们通常理解的帧/每秒, pvi->AvgTimePerFrame用的是时间,单位是100-nanosecond。
可以使用gst-launch-1.0测试以下:
gst-launch-1.0 -v videotestsrc \
! video/x-raw,foramt=YUV2,width=1280,height=720,framerate=30/1 \
! autovideosink
显示效果:
CSourceStream中的DecideBufferSize方法
当确定了媒体类型和格式信息后,作为通常output pin还需要overwiter DecideBufferSize方法,这个方法用来设置sample buffers的大小
HRESULT CVCamStream::DecideBufferSize(IMemAllocator *pAlloc, //pAlloc为指向allocator的指针,allocator管理这buffer
ALLOCATOR_PROPERTIES *pProperties)//ALLOCATOR_PROPERTIES 包含有input pin对buffer的需求
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
HRESULT hr = NOERROR;
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)m_mt.Format();
pProperties->cBuffers = 1; //设置被allocator创建的buffer的多少
pProperties->cbBuffer = pvi->bmiHeader.biSizeImage; //设置buffer的大小,以字节为单位
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties, &Actual);//这是新属性
if (FAILED(hr)) return hr;
if (Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
return NOERROR;
}
如上面的方法,allocator被要求只创建一个buffer,且大小等于1帧(bitmap的大小)。
IAMStreamConfig接口和video Capabilities
始于视频输入设备来说,它们通常支持一些列的格式。例如一个设备可能会支持 16-bit RGB, 32-bit RGB, 和YUYV. 在每个格式里,这个设备又可能会支持一系列的帧大小.
这时候 IAMStreamConfig接口通常被用来报告这个设备支持的所有格式信息,并且允许设置格式信息, 对于capture filter来说,它的output pin需要实现这个接口。
- GetNumberOfCapabilities
HRESULT GetNumberOfCapabilities(
[out] int *piCount,
[out] int *piSize
);
这个接口返回两个数据: 通过piCount获得这个filter支持的媒体类型个数。通过piSize可以获得保存caps信息的结构体的大小,对于视频来说,这个接口体时VIDEO_STREAM_CONFIG_CAPS。
- IAMStreamConfig::GetStreamCaps
HRESULT GetStreamCaps(
[in] int iIndex,
[out] AM_MEDIA_TYPE **ppmt,
[out] BYTE *pSCC
);
这个方法通过索引index获得具体的某个format信息(ppmt指向)和能力信息(pSCC指向),对于视频pSCC指向一个 VIDEO_STREAM_CONFIG_CAPS结构体。
- SetFormat 和GetFormat
GetFormat用于返回一个pin的format信息:当pin已经连接成功,它返回的是当前正在使用的format;如果还没有连接成功,它返回下次连接最合适的format. 特别是如果用户使用了setFormat 设置了一个format, 则GetFormat会返回这个设置的值。
setformat可以用来设置output pin的格式,如果还没有连接了,这个format将被用来做下一次连接,如果已经连接了. 这个方法会尝试重连接。 - VIDEO_STREAM_CONFIG_CAPS
这个结构体用来描述设备的视频能力,包括format和resolution信息:
typedef struct _VIDEO_STREAM_CONFIG_CAPS {
GUID guid; //确定Format类型的GUID
ULONG VideoStandard;//支持的模拟视频标准,数字视频设为0(AnalogVideo_None)
SIZE InputSize; ////输入视频的大小 ---已经废弃
SIZE MinCroppingSize; //允许的最小resSource ---已经废弃
SIZE MaxCroppingSize; //允许的最小resSource ---已经废弃
int CropGranularityX; //resSource的水平increment的度 ---已经废弃
int CropGranularityY; //resSource的垂直increment的度 ---已经废弃
int CropAlignX; //resSource水平对齐 ---已经废弃
int CropAlignY; //resSource垂直对齐 ---已经废弃
SIZE MinOutputSize; //最小输出大小 ---已经废弃
SIZE MaxOutputSize; //最大输出大小 ---已经废弃
int OutputGranularityX; //Granularity of the output width ---已经废弃
int OutputGranularityY; //Granularity of output height. ---已经废弃
int StretchTapsX; //水平stretch的程度 取值[0,1,2,3...] ---已经废弃
int StretchTapsY; //垂直stretch的程度 ---已经废弃
int ShrinkTapsX; //水平Shrink的程度 ---已经废弃
int ShrinkTapsY; //水平Shrink的程度 ---已经废弃
LONGLONG MinFrameInterval; //最小帧间隔 单位100纳秒
LONGLONG MaxFrameInterval; //最大帧间隔 单位100纳秒
LONG MinBitsPerSecond; //Minimum data rate this pin can produce. ---已经废弃
LONG MaxBitsPerSecond; //Maximum data rate this pin can produce. ---已经废弃
} VIDEO_STREAM_CONFIG_CAPS;
IAMStreamConfig::GetStreamCaps将返回这个结构体,应用程序可以使用这个信息output pin的格式。关于它详细的介绍可以参考Video Capabilities和VIDEO_STREAM_CONFIG_CAPS structure。例如对于如下的设置:
MinOutputSize: 160 x 120
MaxOutputSize: 320 x 240
OutputGranularityX: 8 pixels (horizontal step size)
OutputGranularityY: 8 pixels (vertical step size)
下图是这些属性值的解释:
最后我们来看一下,根据我们的媒体和格式类型,实现GetStreamCaps方法:
HRESULT STDMETHODCALLTYPE CVCamStream::GetStreamCaps(int iIndex,
AM_MEDIA_TYPE **pmt, BYTE *pSCC)
{
if (iIndex < 0 )
return E_INVALIDARG;
*pmt = CreateMediaType(&m_mt); //创建媒体类型
DECLARE_PTR(VIDEOINFOHEADER, pvi, (*pmt)->pbFormat); //创建format类型
//设置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));
//设置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);
//创建VIDEO_STREAM_CONFIG_CAPS结构体
DECLARE_PTR(VIDEO_STREAM_CONFIG_CAPS, pvscc, pSCC);
//设置VIDEO_STREAM_CONFIG_CAPS
pvscc->guid = FORMAT_VideoInfo; //媒体类型为FORMAT_VideoInfo
pvscc->VideoStandard = AnalogVideo_None; //不是模拟视频
pvscc->InputSize.cx = pvi->bmiHeader.biWidth; //输入宽度
pvscc->InputSize.cy = pvi->bmiHeader.biHeight; //输入高度
pvscc->MinCroppingSize.cx = pvi->bmiHeader.biWidth; //最小可裁剪宽度 相当于不允许水平裁剪
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; //水平对其
pvscc->CropAlignY = 0; //垂直对齐
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; //最小帧间隔=平均帧播放时间
pvscc->MaxFrameInterval = pvi->AvgTimePerFrame; //最大帧间隔=平均帧播放时间
pvscc->MinBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight
* 2 * 8 * (10000000 / pvi->AvgTimePerFrame); //最小输出数据bit单位
pvscc->MaxBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight
* 2 * 8 * (10000000 / pvi->AvgTimePerFrame); /最大输出数据bit单位
return S_OK;
}
上面有一个关于pin产生数据大小的计算:
pvscc->MinBitsPerSecond = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight
* 2 * 8 * (10000000 / pvi->AvgTimePerFrame);
biWidth 是位图宽度(单位像素),biHeight是位图高度(单位像素),YUV2一个像素需要2个字节,每个字节8bit位。所以biWidth biHeight28就是bitmap的大小。10000000 / pvi->AvgTimePerFrame表示一秒中,可以播放多少帧。我们知道这个值在我们的例子里就是30.
所以最终我们获得了,每秒钟output pin可以传输的bit的大小。他就等于size(bitmap)帧频率。