关于使用DirectShow架构,传输YUV420数据的Filter与Video Renderer Filter连接问题的解决办法。

来源:互联网 发布:货币就业利息通论知乎 编辑:程序博客网 时间:2024/05/21 13:29
主要是对VIDEOINFO的设置要正确。

先给出支持RGB24的代码,  

    VIDEOINFO *pvi = (VIDEOINFO *)m_PreferredMt.AllocFormatBuffer(sizeof(VIDEOINFO));
    ZeroMemory(pvi, sizeof(VIDEOINFO));

    SetPaletteEntries();
    pvi->bmiHeader.biCompression = BI_RGB;
    pvi->bmiHeader.biBitCount    = 24;

    for(int i = 0; i < iPALETTE_COLORS; i++)
    {
        pvi->TrueColorInfo.bmiColors[i].rgbRed      = m_Palette[i].peRed;
        pvi->TrueColorInfo.bmiColors[i].rgbBlue     = m_Palette[i].peBlue;
        pvi->TrueColorInfo.bmiColors[i].rgbGreen    = m_Palette[i].peGreen;
        pvi->TrueColorInfo.bmiColors[i].rgbReserved = 0;
    }

    pvi->bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
    pvi->bmiHeader.biWidth            = 352;
    pvi->bmiHeader.biHeight            = 288;
    pvi->bmiHeader.biPlanes            = 1;
    pvi->bmiHeader.biSizeImage        = GetBitmapSize(&pvi->bmiHeader);
    pvi->bmiHeader.biClrImportant    = 0;
    pvi->bmiHeader.biClrImportant    = 0;


    SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
    SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle

    m_PreferredMt.SetType(&MEDIATYPE_Video);
    m_PreferredMt.SetTemporalCompression(FALSE);
    m_PreferredMt.SetFormatType(&(m_Filter->formattype));

    const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
    m_PreferredMt.SetSubtype(&SubTypeGUID);
//    m_PreferredMt.SetSubtype(&MEDIASUBTYPE_YUY2);

    m_PreferredMt.SetSampleSize(pvi->bmiHeader.biSizeImage);

GetBitmapSubtype(&pvi->bmiHeader);得到的媒体类型为MEDIASUBTYPE_RGB24,如果其他设置不变的话,只需要修改pvi->bmiHeader.biBitCount    = 24;就可以对RGB32,RGB16,RGB8进行支持。


以下是对YUV420数据的支持,媒体类型WMMEDIASUBTYPE_I420,要支持这个类型,请记住包含头文件#include <wmsdkidl.h>:
    VIDEOINFOHEADER   vih; 
    memset(&vih,0,sizeof(vih)); 
    vih.bmiHeader.biCompression   =   MAKEFOURCC('I','4','2','0'); 
    vih.bmiHeader.biBitCount      =   16; 
    vih.bmiHeader.biSize          =   sizeof(BITMAPINFOHEADER); 
    vih.bmiHeader.biWidth         =   352;//Your   size.x 
    vih.bmiHeader.biHeight        =   288;//Your   size.y 
    vih.bmiHeader.biPlanes        =   1; 
    vih.bmiHeader.biSizeImage     =   GetBitmapSize(&vih.bmiHeader); 
    vih.bmiHeader.biClrImportant  =   0; 

    m_PreferredMt.SetType(&MEDIATYPE_Video); 
    m_PreferredMt.SetFormatType(&FORMAT_VideoInfo); 
    m_PreferredMt.SetFormat((BYTE*)&vih,sizeof(vih)); 
    m_PreferredMt.SetSubtype(&WMMEDIASUBTYPE_I420); 
    m_PreferredMt.SetSampleSize(vih.bmiHeader.biSizeImage);

之后试了几个其他的模式,也能正常
pViOut->bmiHeader.biCompression = MAKEFOURCC('I','4','2','0');
pViOut->bmiHeader.biBitCount = 12;
pMediaType->SetSubtype(&MEDIASUBTYPE_YV12);

pViOut->bmiHeader.biCompression = MAKEFOURCC('I','4','2','0');
pViOut->bmiHeader.biBitCount = 16;
pMediaType->SetSubtype(&MEDIASUBTYPE_YV12);
都可以。

WMMEDIASUBTYPE_I420只有16可以,12不行

MEDIASUBTYPE_YV12
12
MAKEFOURCC('Y','V','1','2');
我试了,画面不正常,色彩有点奇怪

MEDIASUBTYPE_YV12
16
MAKEFOURCC('Y','V','1','2');
色彩和使用12一样奇怪

原创粉丝点击