美文网首页
使用Gstreamer 作为数据源输出视频数据 II 媒体类型

使用Gstreamer 作为数据源输出视频数据 II 媒体类型

作者: Charles_linzc | 来源:发表于2021-11-11 16:09 被阅读0次

    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 系统中的位置,可以看到它是一视频编码后更外边的包。

    image.png

    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类型:


    image.png

    在上面的媒体对于视频来说,在常用的就是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 **
    例如使用如上命令产生的效果:

    image.png

    在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
    

    显示效果:


    image.png

    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需要实现这个接口。

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

    这个接口返回两个数据: 通过piCount获得这个filter支持的媒体类型个数。通过piSize可以获得保存caps信息的结构体的大小,对于视频来说,这个接口体时VIDEO_STREAM_CONFIG_CAPS

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

    这个方法通过索引index获得具体的某个format信息(ppmt指向)和能力信息(pSCC指向),对于视频pSCC指向一个 VIDEO_STREAM_CONFIG_CAPS结构体。

    • SetFormatGetFormat
      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 CapabilitiesVIDEO_STREAM_CONFIG_CAPS structure。例如对于如下的设置:
    MinOutputSize: 160 x 120
    MaxOutputSize: 320 x 240
    OutputGranularityX: 8 pixels (horizontal step size)
    OutputGranularityY: 8 pixels (vertical step size)
    下图是这些属性值的解释:

    image.png

    最后我们来看一下,根据我们的媒体和格式类型,实现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)
    帧频率。

    相关文章

      网友评论

          本文标题:使用Gstreamer 作为数据源输出视频数据 II 媒体类型

          本文链接:https://www.haomeiwen.com/subject/tyerzltx.html