How do I copy the video stream from a buffer of webcam in C++ under Windows?

Posted on 2009-02-09
Last Modified: 2013-12-14
I work on a C++ project similar to SplitCam - and I couldn't find out any way to create DirectShow Source Filter without input pins, that distributes video stream from a webcam to its output pin. I can neither find any API to initiate connection with a webcam from my filter, nor copy the video stream from a buffer of webcam to some temporary destination such as shared memory to use IPC. Please help.
Question by:mkruebl
    LVL 3

    Expert Comment


    Author Comment

    Yes, DirectShow can easily capture frames, but I need to access pixels of each frame to store them into shared memory.

    Currently, I generate random frame each time it is called:

    // This is where we insert the DIB bits into the video stream.
    // FillBuffer is called once for every sample in the stream.
    HRESULT MyOutputPin::FillBuffer(IMediaSample *pSample) {
          CheckPointer(pSample, E_POINTER);
        BYTE *pData;
        long lDataLen;

          lDataLen = pSample->GetSize();

          ZeroMemory(pData, lDataLen);
              CAutoLock cAutoLockShared(&m_cSharedState);
                long i;
                for (i = 0; i < lDataLen; i++) {
                      if (i & 1) {
                            pData[i] = rand() % 255;
                      } else {
                            pData[i] = rand() % 255;

        return S_OK; // S_FALSE End of stream, S_OK = filled

    It will look similarly to when you tell me how to get BYTE *pData from each frame grabbed from a webcam.
    LVL 3

    Accepted Solution

    You can use SampleGrabber to access pixels of each frame.

    See the code below... I stripped all error checking for brevity... i may have striped something else by mistake... but it may give you some directions.

    The 'mDShowSampleGrabberCB' object will be called every frame, as soon as a new frame is available.

    //Callback class
    class SampleGrabberCallback : public ISampleGrabberCB
            referenceCount = 0;
        /// Mandatory overrides
        STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
            *ppvObject = static_cast<ISampleGrabberCB*>(this);
            return S_OK;
        STDMETHODIMP_(ULONG) AddRef(void)  { return ++referenceCount; }
        STDMETHODIMP_(ULONG) Release(void)
            if(referenceCount == 1)
                // clean Up
            return --referenceCount;
        // We receive here a pointer to the original buffer (we need to make a copy)
        STDMETHODIMP SampleCB(double Time, IMediaSample* pSample)
            unsigned char* ptrBuffer;
            HRESULT hr = pSample->GetPointer(&ptrBuffer);
            if(hr == S_OK)
                // do something with the buffer here...
                // something like:
                // int bufferLength = pSample->GetActualDataLength();
                // memcpy(mybuffer,ptrBuffer,bufferLength);
            return S_OK;
        // We won't use this... it returns a copy so it has more overhead
        STDMETHODIMP BufferCB(double Time, BYTE* pBuffer, long BufferLen){
           return E_NOTIMPL;
        unsigned int referenceCount;
    };  // SampleGrabberCallback
    /// then, somewhere in your code
    // Create the sample grabber filter and add it to the graph
    IBaseFilter* mDShowFilterGrabber;
    hr = CoCreateInstance(CLSID_SampleGrabber,NULL,
    hr = pGraph->AddFilter(mDShowFilterGrabber,L"Sample Grabber");
    // Create the sample grabber
    ISampleGrabber* mDShowSampleGrabber;
    hr = mDShowFilterGrabber->QueryInterface(IID_ISampleGrabber,
    // Sets the sample grabber media type
    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;
    hr = mDShowSampleGrabber->SetMediaType(&mt);
    // Create the callback
    SampleGrabberCallback* mDShowSampleGrabberCB;
    mDShowSampleGrabberCB = new SampleGrabberCallback();
    //Tell the grabber to use our callback function
    //0 is for SampleCB and 1 for BufferCB
    hr = mDShowSampleGrabber->SetCallback(mDShowSampleGrabberCB,0);

    Open in new window


    Author Closing Comment

    That's exactly it! Thank you so much vhpgomes.

    Featured Post

    How your wiki can always stay up-to-date

    Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
    - Increase transparency
    - Onboard new hires faster
    - Access from mobile/offline

    Join & Write a Comment

    For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
    How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from ( Go to that link and select download selenium in the right hand columnThat will then direct you to their downlo…
    The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
    This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

    728 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    14 Experts available now in Live!

    Get 1:1 Help Now