avicapture.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:5k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // avicapture.cpp
  2. //
  3. // Copyright (C) 2001-2008, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include <cmath>
  10. #include "../celengine/gl.h"
  11. #include "../celengine/glext.h"
  12. #include <windowsx.h>
  13. #include <celutil/debug.h>
  14. #include "avicapture.h"
  15. using namespace std;
  16. AVICapture::AVICapture() :
  17.     width(-1),
  18.     height(-1),
  19.     frameRate(30.0f),
  20.     frameCounter(0),
  21.     capturing(false),
  22.     aviFile(NULL),
  23.     aviStream(NULL),
  24.     compAviStream(NULL),
  25.     image(NULL)
  26. {
  27.     AVIFileInit();
  28. }
  29. AVICapture::~AVICapture()
  30. {
  31.     cleanup();
  32.     AVIFileExit();
  33. }
  34. bool AVICapture::start(const string& filename,
  35.                        int w, int h,
  36.                        float fps)
  37. {
  38.     if (capturing)
  39.         return false;
  40.     width = w;
  41.     height = h;
  42.     frameRate = fps;
  43.     if (HIWORD(VideoForWindowsVersion()) < 0x010a)
  44.     {
  45.         // We need to be running on version 1.1 or later
  46.         return false;
  47.     }
  48.     // Compute the width of a row in bytes; pad so that rows are aligned on
  49.     // 4 byte boundaries.
  50.     int rowBytes = (width * 3 + 3) & ~0x3;
  51.     image = new unsigned char[rowBytes * height]; 
  52.     HRESULT hr = AVIFileOpenA(&aviFile,
  53.                               filename.c_str(),
  54.                               OF_WRITE | OF_CREATE,
  55.                               NULL);
  56.     if (hr != AVIERR_OK)
  57.     {
  58.         DPRINTF(0, "Erroring creating avi file for capture.n");
  59.         return false;
  60.     }
  61.     AVISTREAMINFO info;
  62.     ZeroMemory(&info, sizeof info);
  63.     info.fccType = streamtypeVIDEO;
  64.     info.fccHandler = 0;
  65.     info.dwScale = 1;
  66.     info.dwRate = (DWORD) floor(frameRate + 0.5f);
  67.     info.dwSuggestedBufferSize = rowBytes * height;
  68.     SetRect(&info.rcFrame, 0, 0, width, height);
  69.     hr = AVIFileCreateStream(aviFile, &aviStream, &info);
  70.     if (hr != AVIERR_OK)
  71.     {
  72.         DPRINTF(0, "Error %08x creating AVI stream.n", hr);
  73.         cleanup();
  74.         return false;
  75.     }
  76.     // Display a dialog to allow the user to select compression options
  77.     AVICOMPRESSOPTIONS options;
  78.     AVICOMPRESSOPTIONS* arrOptions[1] = { &options };
  79.     ZeroMemory(&options, sizeof options);
  80.     if (!AVISaveOptions(NULL, 0, 1, &aviStream, 
  81.                         (LPAVICOMPRESSOPTIONS*) &arrOptions))
  82.     {
  83.         // The user either clicked on cancel or there was an error
  84.         cleanup();
  85.         return false;
  86.     }
  87.     hr = AVIMakeCompressedStream(&compAviStream, aviStream, &options, NULL);
  88.     if (hr != AVIERR_OK)
  89.     {
  90.         DPRINTF(0, "Error %08x creating compressed AVI stream.n", hr);
  91.         cleanup();
  92.         return false;
  93.     }
  94.     BITMAPINFOHEADER bi;
  95.     ZeroMemory(&bi, sizeof bi);
  96.     bi.biSize = sizeof bi;
  97.     bi.biWidth = width;
  98.     bi.biHeight = height;
  99.     bi.biPlanes = 1;
  100.     bi.biBitCount = 24;
  101.     bi.biCompression = BI_RGB;
  102.     bi.biSizeImage = rowBytes * height;
  103.     bi.biXPelsPerMeter = 0;
  104.     bi.biYPelsPerMeter = 0;
  105.     bi.biClrUsed = 0;
  106.     bi.biClrImportant = 0;
  107.     hr = AVIStreamSetFormat(compAviStream, 0, &bi, sizeof bi);
  108.     if (hr != AVIERR_OK)
  109.     {
  110.         DPRINTF(0, "AVIStreamSetFormat failed: %08xn", hr);
  111.         cleanup();
  112.         return false;
  113.     }
  114.     capturing = true;
  115.     frameCounter = 0;
  116.     return true;
  117. }
  118. bool AVICapture::end()
  119. {
  120.     capturing = false;
  121.     cleanup();
  122.     return true;
  123. }
  124. bool AVICapture::captureFrame()
  125. {
  126.     if (!capturing)
  127.         return false;
  128.     // Get the dimensions of the current viewport
  129.     int viewport[4];
  130.     glGetIntegerv(GL_VIEWPORT, viewport);
  131.     int x = viewport[0] + (viewport[2] - width) / 2;
  132.     int y = viewport[1] + (viewport[3] - height) / 2;
  133.     glReadPixels(x, y, width, height,
  134.                  GL_BGR_EXT, GL_UNSIGNED_BYTE,
  135.                  image);
  136.     int rowBytes = (width * 3 + 3) & ~0x3;
  137.     LONG samplesWritten = 0;
  138.     LONG bytesWritten = 0;
  139.     HRESULT hr = AVIStreamWrite(compAviStream,
  140.                                 frameCounter,
  141.                                 1,
  142.                                 image,
  143.                                 rowBytes * height,
  144.                                 AVIIF_KEYFRAME,
  145.                                 &samplesWritten,
  146.                                 &bytesWritten);
  147.     if (hr != AVIERR_OK)
  148.     {
  149.         DPRINTF(0, "AVIStreamWrite failed on frame %dn", frameCounter);
  150.         return false;
  151.     }
  152.     // printf("Writing frame: %d  %d => %d bytesn",
  153.     //        frameCounter, rowBytes * height, bytesWritten);
  154.     frameCounter++;
  155.     return true;
  156. }
  157. void AVICapture::cleanup()
  158. {
  159.     if (aviStream != NULL)
  160.     {
  161.         AVIStreamRelease(aviStream);
  162.         aviStream = NULL;
  163.     }
  164.     if (compAviStream != NULL)
  165.     {
  166.         AVIStreamRelease(compAviStream);
  167.         compAviStream = NULL;
  168.     }
  169.     if (aviFile != NULL)
  170.     {
  171.         AVIFileRelease(aviFile);
  172.         aviFile = NULL;
  173.     }
  174.     if (image != NULL)
  175.     {
  176.         delete[] image;
  177.         image = NULL;
  178.     }
  179. }
  180. int AVICapture::getWidth() const
  181. {
  182.     return width;
  183. }
  184. int AVICapture::getHeight() const
  185. {
  186.     return height;
  187. }
  188. float AVICapture::getFrameRate() const
  189. {
  190.     return frameRate;
  191. }
  192. int AVICapture::getFrameCount() const
  193. {
  194.     return frameCounter;
  195. }