0

I have develop an application which is taking snapshot of DESKTOP at every 1000/30Milliseconds. And application will run for 10 minute. So in 10 minute it should save 18000 snapshot but it is only around 80 snapshots. I am not getting why this is happening.

My Code is here:-

#include "windows.h" // should be less than and greater than instead of \"
#include "string.h"
int CaptureBMP(LPCTSTR szFile)
{
    // Source[1]
    HDC hdcScr, hdcMem;
    HBITMAP hbmScr;
    BITMAP bmp;
    int iXRes, iYRes;

    // Create a normal DC and a memory DC for the entire screen. The
    // normal DC provides a "snapshot" of the screen contents. The
    // memory DC keeps a copy of this "snapshot" in the associated
    // bitmap.
    hdcScr = CreateDC("DISPLAY", NULL, NULL, NULL);
    hdcMem = CreateCompatibleDC(hdcScr);

    iXRes = GetDeviceCaps(hdcScr, HORZRES);
    iYRes = GetDeviceCaps(hdcScr, VERTRES);

    // Create a compatible bitmap for hdcScreen.
    hbmScr = CreateCompatibleBitmap(hdcScr, iXRes, iYRes);
    if (hbmScr == 0) return 0;

    // Select the bitmaps into the compatible DC.
    if (!SelectObject(hdcMem, hbmScr)) return 0;

    // Copy color data for the entire display into a
    // bitmap that is selected into a compatible DC.
    if (!StretchBlt(hdcMem,
        0, 0, iXRes, iYRes,
        hdcScr,
        0, 0, iXRes, iYRes,
        SRCCOPY))

        return 0;

    // Source[2]
    PBITMAPINFO pbmi;
    WORD cClrBits;

    // Retrieve the bitmap's color format, width, and height.
    if (!GetObject(hbmScr, sizeof(BITMAP), (LPSTR) &bmp)) return 0;

    // Convert the color format to a count of bits.
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
    if (cClrBits == 1)
        cClrBits = 1;
    else if (cClrBits <= 4)
        cClrBits = 4;
    else if (cClrBits <= 8)
        cClrBits = 8;
    else if (cClrBits <= 16)
        cClrBits = 16;
    else if (cClrBits <= 24)
        cClrBits = 24;
    else cClrBits = 32;

    // Allocate memory for the BITMAPINFO structure. (This structure
    // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
    // data structures.)
    if (cClrBits != 24)
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                sizeof(BITMAPINFOHEADER) +
                sizeof(RGBQUAD) * (1 << cClrBits));

    // There is no RGBQUAD array for the 24-bit-per-pixel format.
    else
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                sizeof(BITMAPINFOHEADER));

    // Initialize the fields in the BITMAPINFO structure.
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = bmp.bmWidth;
    pbmi->bmiHeader.biHeight = bmp.bmHeight;
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
    if (cClrBits < 24)
        pbmi->bmiHeader.biClrUsed = (1 << cClrBits);

    // If the bitmap is not compressed, set the BI_RGB flag.
    pbmi->bmiHeader.biCompression = BI_RGB;

    // Compute the number of bytes in the array of color
    // indices and store the result in biSizeImage.
    pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8
                                    * pbmi->bmiHeader.biHeight * cClrBits;

    // Set biClrImportant to 0, indicating that all of the
    // device colors are important.
    pbmi->bmiHeader.biClrImportant = 0;

    HANDLE hf;                  // file handle
    BITMAPFILEHEADER hdr;       // bitmap file-header
    PBITMAPINFOHEADER pbih;     // bitmap info-header
    LPBYTE lpBits;              // memory pointer
    DWORD dwTotal;              // total count of bytes
    DWORD cb;                   // incremental count of bytes
    BYTE *hp;                   // byte pointer
    DWORD dwTmp;

    pbih = (PBITMAPINFOHEADER) pbmi;
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    if (!lpBits) return 0;

    // Retrieve the color table (RGBQUAD array) and the bits
    // (array of palette indices) from the DIB.
    if (!GetDIBits(hdcMem, hbmScr, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS)) return 0;

    // Create the .BMP file.
    hf = CreateFile(szFile,
                    GENERIC_READ | GENERIC_WRITE,
                    (DWORD) 0,
                    NULL,
                    CREATE_ALWAYS,
                    FILE_ATTRIBUTE_NORMAL,
                    (HANDLE) NULL);
    if (hf == INVALID_HANDLE_VALUE) return 0;

    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"

    // Compute the size of the entire file.
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
                 pbih->biSize + pbih->biClrUsed *
                 sizeof(RGBQUAD) + pbih->biSizeImage);
    hdr.bfReserved1 = 0;
    hdr.bfReserved2 = 0;

    // Compute the offset to the array of color indices.
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
                    pbih->biSize + pbih->biClrUsed *
                    sizeof (RGBQUAD);

    // Copy the BITMAPFILEHEADER into the .BMP file.
    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) return 0;

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
    if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
                + pbih->biClrUsed * sizeof (RGBQUAD),
                (LPDWORD) &dwTmp, NULL))
        return 0;

    // Copy the array of color indices into the .BMP file.
    dwTotal = cb = pbih->biSizeImage;
    hp = lpBits;
    if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp, NULL)) return 0;

    // Close the .BMP file.
    if (!CloseHandle(hf)) return 0;

    // Free memory.
    GlobalFree((HGLOBAL)lpBits);
    ReleaseDC(0, hdcScr);
    ReleaseDC(0, hdcMem);

    return 1;
} 

void main()
{
    int index =0;

    char str[50];      
    char pmp[10]=".bmp";
    LPCTSTR szFile;
    Sleep(5000);
    DWORD  tickes=0;
    DWORD timespan = 1000/30;
    DWORD diff ;
    DWORD  entry=GetTickCount() +30000;
    while(entry>tickes)
    {
        char num[500]="C:\\SANSHOT\\"; 
        diff=GetTickCount() - tickes;
        tickes=GetTickCount();
        if(diff<timespan)
        {
            Sleep(timespan-diff);

        }
        itoa(index, str, 10);
        strcat(num,str);
        strcat(num,pmp);
        szFile = num;
        CaptureBMP(szFile);
        index++;

    }

}

I don't know what and where is the problem.

Can anybody help me to short-out this problem.

Thanks...

Mayank Prabhakar
  • 133
  • 2
  • 6
  • 14
  • I should tell you one thing first is that 30fps snapshot in bmp format should normally be beyond you hard drive's bandwidth. – BlueWanderer May 11 '12 at 10:34
  • @BlueWanderer Thank You for your reply... So, I want to ask you that how much fps I can get with hard drive's bandwidth. – Mayank Prabhakar May 11 '12 at 10:41
  • Since you got 80 frames in 30sec... 2.6fps I guess. Normally if you want to capture screen as to stream, you have to capture the dirty area of the screen (and I forgot how to do it). Not only your hard drive, sometime the GPU to CPU interconnection is lack of bandwidth, too. – BlueWanderer May 11 '12 at 10:57
  • @BlueWanderer: Since you have the previous bitmap as well, the "dirty area" is just the area where they differ. – MSalters May 12 '12 at 12:59
  • @MSalters If you have already got the bitmap, you might have already killed the bus between CPU and GPU, too. Most video encoders know dirty area better than any of us, if we have the bitmaps. The problem is to get less pixel data before we know the picture. – BlueWanderer May 12 '12 at 15:04
  • @BlueWanderer: The GPU-CPU bus is very wide, and unlikely to kill you. It does have a poor latency, typically, but that matters for single pixel ops. When you grab an entire screen, a few hundred microseconds latency won't kill you. – MSalters May 14 '12 at 07:50
  • @MSalters more than 33ms will kill Mayank, though. If you've ever written a screen capture software and have tested it on a lot of devices, you'd know how narrow that bus sometimes could be. And if we already have the bitmap, why bother the dirty areas? Encoders can even detect motions. – BlueWanderer May 14 '12 at 10:03

1 Answers1

0

I think your problem is the while condition. Your program isn't running for 10min, but for about 30secs (DWORD entry=GetTickCount() + 30000). Then the condition entry > tickes is met and the loop aborts. And in this short time, your app just managed to write 80 bmp's. If you want it to run 10 minutes the number must be not 30000 but 600000 (10min * 60 * 1000 = 600000ms)

AquilaRapax
  • 1,086
  • 8
  • 22
  • Thank You for your Reply... It my mistake that I have written (DWORD entry=GetTickCount() + 30000) here.I have also tried with (DWORD entry=GetTickCount() + 6000000) but I was getting same result. – Mayank Prabhakar May 11 '12 at 10:54
  • Running your code, i realized, that you (let) create a huge amount of memory, which is not freed. Thus my system has frozen after only some minutes due to lack of ram (i have 8GB!). Before this happens it became very, very slow and your program wrote the files slower and slower (and thus lesser). I didn't figure out all memory leaks but after adding the following lines to the end of the CreateBitmap-method the program runs more stable: `DeleteDC(hdcScr)`(instead of ReleaseDC),`DeleteDC(hdcMem)`(instead of ReleaseDC),`LocalFree(pbmi)`,`DeleteObject(hbmScr)` – AquilaRapax May 11 '12 at 12:00