0

I am trying to modify the existing AmCap application, available through Microsoft's SDK Direct Show samples, in order to get an image of the captured stream when I press the space button. Below is the point in which I am handling the space keydown.

        case WM_KEYDOWN:
        if((GetAsyncKeyState(VK_ESCAPE) & 0x01) && gcap.fCapturing)
        {
            StopCapture();
            if(gcap.fWantPreview)
            {
                BuildPreviewGraph();
                StartPreview();
            }
        }
        else if ((GetAsyncKeyState(VK_SPACE) & 0x01))
        {
            IMediaControl *pMC = NULL;
            HRESULT hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);

            if (SUCCEEDED(hr)){
                hr=pMC->Pause();
                if (SUCCEEDED(hr)){
                    CaptureImage(TEXT("C:\\output.bmp"));
                    pMC->Run();
                    pMC->Release();
                }else
                    ErrMsg(TEXT("Failed to pause stream!  hr=0x%x"), hr);
            }
            else
                ErrMsg(TEXT("Cannot grab image"));
        }
        break;

Below is the contents of the CaptureImage function.

HRESULT hr;

SmartPtr<IBasicVideo> pWC;

// If we got here, gcap.pVW is not NULL 
ASSERT(gcap.pVW != NULL);
hr = gcap.pVW->QueryInterface(IID_IBasicVideo, (void**)&pWC);

if (pWC)
{
    long bufSize;
    long *lpCurrImage = NULL;
    pWC->GetCurrentImage(&bufSize, NULL);

    lpCurrImage = (long *)malloc(bufSize);
    //

    // Read the current video frame into a byte buffer.  The information
    // will be returned in a packed Windows DIB and will be allocated
    // by the VMR.
    hr = pWC->GetCurrentImage(&bufSize, lpCurrImage);
    if (SUCCEEDED(hr))
    {
        HANDLE fh;
        BITMAPFILEHEADER bmphdr;
        BITMAPINFOHEADER bmpinfo;
        DWORD nWritten;

        memset(&bmphdr, 0, sizeof(bmphdr));
        memset(&bmpinfo, 0, sizeof(bmpinfo));

        bmphdr.bfType = ('M' << 8) | 'B';
        bmphdr.bfSize = sizeof(bmphdr) + sizeof(bmpinfo) + bufSize;
        bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(bmpinfo);

        bmpinfo.biSize = sizeof(bmpinfo);
        bmpinfo.biWidth = 640;
        bmpinfo.biHeight = 480;
        bmpinfo.biPlanes = 1;
        bmpinfo.biBitCount = 32;

        fh = CreateFile(TEXT("C:\\Users\\mike\\Desktop\\output.bmp"),
            GENERIC_WRITE, 0, NULL,
            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        WriteFile(fh, &bmphdr, sizeof(bmphdr), &nWritten, NULL);
        WriteFile(fh, &bmpinfo, sizeof(bmpinfo), &nWritten, NULL);
        WriteFile(fh, lpCurrImage, bufSize, &nWritten, NULL);
        CloseHandle(fh);

        ErrMsg(TEXT("Captured current image to %s"),  szFile);
        return TRUE;
    }
    else
    {
        ErrMsg(TEXT("Failed to capture image!  hr=0x%x"), hr);
        return FALSE;
    }
}

return FALSE;

The problem is that when I am trying to run the app, I receive an HRESULT (0x8000ffff) error when the GetCurrentImage function is being called.

On the other hand in case I execute the app through the VS debugger the code works just fine.

I tried to add a Sleep just after the stream pMC->Pause(), assuming that the problem was timing issue but that did not work.

Any ideas would be extremely helpful!

Thank you in advance.

mike1821
  • 1
  • 4
  • If you call it before the first video frame is delivered to the video renderer, you get the error - it does not yet have a frame to get you back. – Roman R. Jan 02 '16 at 20:54
  • But I do see the live capture stream in the main window. This means that frames are being delivered to the rendered. right? – mike1821 Jan 02 '16 at 21:34
  • Yes, it is not a problem then. Next thing is the following: your `IBasicVideo` is looking for first `IBasicVideo` implementation among filters of the graph and forwards call there. Your filter graph might have another wrong or unused renderer which is giving the problem. To troubleshooting this, you need to do one of the two or both: (1) review effective topology for another renderer (including added automatically - which you are not aware of), and (2) QI `IBasicVideo` from your known good video renderer instead of filter graph and use it. – Roman R. Jan 02 '16 at 22:43
  • Hi, thanks for the info. I am not sure I understood point (1) above. How am I suppose to review the rendered topology? – mike1821 Jan 04 '16 at 03:51
  • Options: (a) do `EnumFilters` after you finished graph construction to see if there is anything there, that you are not aware of, (b) [How can I reverse engineer a DirectShow graph?](http://stackoverflow.com/questions/27832/how-can-i-reverse-engineer-a-directshow-graph) – Roman R. Jan 04 '16 at 10:19

0 Answers0