0

感谢您的帮助,我能够更好地搜索正确的单词来使用 directshow。我在这里找到了如何使用 SampleGrabber 对象的教程:http: //msdn.microsoft.com/en-us/library/windows/desktop/dd407288%28v=vs.85%29.aspx

我可以实现它并对其进行一些修改,这样它不仅可以保存第一帧,还可以将每个帧保存为 PNG。为此,我使用电晕。但是,我只是猜测了一些东西,不太清楚哪些缓冲区包含我的数据以及以哪种形式。

所以,我基本上有 3 个问题:
我使用 SavePNG 对吗?生成的图像是颠倒的!
我可以用连接到相机的视频替换 BaseFilter 吗?
包含 pBuffer 我的 Imagedata,所以我可以通过简单地键入 pBuffer[123] 来获取 rgb 字节信息?

我正在使用 embarcadero 的 C++-Builder (XE2 16)。

这是我在网站上找到的代码,稍作修改(删除了错误处理以获得更好的视图。在每个 hr=... 之后有一个失败检查):

void __fastcall TForm1::btn_kameraClick(TObject *Sender)
{
HRESULT hr = S_OK;
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEventEx *pEvent = NULL;
    IBaseFilter *pGrabberF = NULL;
    ISampleGrabber *pGrabber = NULL;
    IBaseFilter *pSourceF = NULL;
    IEnumPins *pEnum = NULL;
    IPin *pPin = NULL;
    IBaseFilter *pNullF = NULL;
    BYTE *pBuffer = NULL;

    hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGraph));
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGrabberF));
    hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber));

    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(mt));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;

    hr = pGrabber->SetMediaType(&mt);
    hr = pGraph->AddSourceFilter(L"C:/Users/Julian/Desktop/homogenität/1,1x_2,7y.mpg", L"Source", &pSourceF);
    hr = pSourceF->EnumPins(&pEnum);
    while (S_OK == pEnum->Next(1, &pPin, NULL))
    {
        hr = ConnectFilters(pGraph, pPin, pGrabberF);
        SafeRelease(&pPin);
        if (SUCCEEDED(hr))break;
    }
    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pNullF));
    hr = pGraph->AddFilter(pNullF, L"Null Filter");
    hr = ConnectFilters(pGraph, pGrabberF, pNullF);
    hr = pGrabber->SetOneShot(TRUE);
    hr = pGrabber->SetBufferSamples(TRUE);
    long evCode=0;
    long cbBuffer=0;
    hr = pControl->Run();
    hr = pEvent->WaitForCompletion(INFINITE, &evCode);
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
    pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer);
    hr = pGrabber->GetConnectedMediaType(&mt);

    CComQIPtr< IMediaSeeking, &IID_IMediaSeeking > pSeeking( pGraph );


//  for(int i=0;i<10;i++){
    bool hui=true;int i=0;
    while(hui){
    REFERENCE_TIME Start = i * UNITS;
    hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning,NULL, AM_SEEKING_NoPositioning );
//  Sleep(10);
    hr = pEvent->WaitForCompletion(INFINITE,&evCode);
    if(hr!=0)hui=false;
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
    if ((mt.formattype == FORMAT_VideoInfo) &&(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&(mt.pbFormat != NULL))
    {
        VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;

//      hr = WriteBitmap(("hui"+(String)i+".bmp").c_str(), &pVih->bmiHeader, mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer);
        hr = SavePNG(i,pBuffer, pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight);
    }
    else hr = VFW_E_INVALIDMEDIATYPE;
    i++;
    }
    FreeMediaType(mt);

done:
    CoTaskMemFree(pBuffer);
    SafeRelease(&pPin);
    SafeRelease(&pEnum);
    SafeRelease(&pNullF);
    SafeRelease(&pSourceF);
    SafeRelease(&pGrabber);
    SafeRelease(&pGrabberF);
    SafeRelease(&pControl);
    SafeRelease(&pEvent);
    SafeRelease(&pGraph);

}
bool SavePNG(int i, Byte* m_pImageData,long m_Width,long m_Height)
{
    // Make sure there is image data

    if (!m_pImageData)
        return false;

    stringstream FilePath;
    FilePath << "hui"<< i<<".png";
    // Create a corona image
    corona::Image* pImage = corona::CreateImage(m_Width, m_Height, corona::PF_R8G8B8, m_pImageData);

    // Make sure the image was created
    if (!pImage)
        return false;

    // Save the image to a PNG file
    corona::SaveImage(FilePath.str().c_str(), corona::FF_PNG, pImage);

    // Delete the corona image
    delete pImage;

    // Nothing went wrong
    return true;
}

我希望我没有做任何可怕的错误......我真的试图研究一切^^有人知道我上面的3个问题吗?我在这里发现了一些非常错误的地方,我也很感激你告诉我,所以我可以修复和改进。

问候,朱利安

4

1 回答 1

0

现在,当您拥有 24 位 RGB 格式的视频帧时,您只需将其压缩为 PNG。您可以在这里选择:

可能,C++ bulder 也有要涵盖PNG的本地类。

您使用的 PS DirectShow API 不是 DirectX,它是 Windows 核心 SDK 的一部分。

于 2012-08-18T14:16:10.967 回答