VFWCapture.cpp
Go to the documentation of this file.
1 // ****************************************************************************
2 // This file is part of the Integrating Vision Toolkit (IVT).
3 //
4 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
5 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
6 //
7 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // 3. Neither the name of the KIT nor the names of its contributors may be
21 // used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
28 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // ****************************************************************************
35 // ****************************************************************************
36 // Filename: VFWCapture.cpp
37 // Author: Pedram Azad
38 // Date: 2005
39 // ****************************************************************************
40 
41 
42 // ****************************************************************************
43 // Includes
44 // ****************************************************************************
45 
46 #include "VFWCapture.h"
47 
48 #include "Image/ByteImage.h"
49 #include "Image/ImageProcessor.h"
50 #include "Helpers/helpers.h"
51 
52 #include <vfw.h>
53 #include <wingdi.h>
54 
55 
56 // ****************************************************************************
57 // Defines
58 // ****************************************************************************
59 
60 // FOURCC codes understood by the capture code
61 #define BI_I420 0x30323449
62 #define BI_YUY2 0x32595559
63 
64 
65 // ****************************************************************************
66 // Global and static variables
67 // ****************************************************************************
68 
69 CRITICAL_SECTION critical_section;
71 
72 
73 // ****************************************************************************
74 // Static functions
75 // ****************************************************************************
76 
77 #define myClip(x) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (unsigned char) (x))
78 static inline void yuv2rgb(unsigned char y, unsigned char u, unsigned char v, unsigned char *out)
79 {
80  int C = (int) y - 16;
81  int D = (int) u - 128;
82  int E = (int) v - 128;
83 
84  int R = (( 298 * C + 409 * E + 128) >> 8);
85  int G = (( 298 * C - 100 * D - 208 * E + 128) >> 8);
86  int B = (( 298 * C + 516 * D + 128) >> 8);
87 
88  out[0] = myClip(R);
89  out[1] = myClip(G);
90  out[2] = myClip(B);
91 }
92 #undef myClip
93 
94 static LRESULT CALLBACK CallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
95 {
96  EnterCriticalSection(&critical_section);
97 
98  if (!pCapturedImage)
99  {
100  LeaveCriticalSection(&critical_section);
101  return (LRESULT) TRUE;
102  }
103 
104  pCapturedImage->pixels = (unsigned char *) lpVHdr->lpData;
105 
106  LeaveCriticalSection(&critical_section);
107 
108  return (LRESULT) TRUE;
109 }
110 
111 
112 // ****************************************************************************
113 // Constructor / Destructor
114 // ****************************************************************************
115 
116 CVFWCapture::CVFWCapture(int nDriverIndex)
117 {
118  pCapturedImage = 0;
119  m_hCaptureWnd = 0;
120 
121  m_nWidth = -1;
122  m_nHeight = -1;
123  m_nBitsPerPixel = 0;
125 
126  m_nDriverIndex = nDriverIndex;
127  m_bFlipY = false;
128 
129  m_bCameraOpened = false;
130 
131  for (int i = 0; i < 1024; i++)
132  m_clip[i] = i < 256 ? i : 255;
133 
134  InitializeCriticalSection(&critical_section);
135 }
136 
138 {
139  CloseCamera();
140 
141  if (m_hCaptureWnd)
142  {
143  DestroyWindow(m_hCaptureWnd);
144  m_hCaptureWnd = 0;
145  }
146 
147  if (pCapturedImage)
148  delete pCapturedImage;
149 
150  DeleteCriticalSection(&critical_section);
151 }
152 
153 
154 // ****************************************************************************
155 // Methods
156 // ****************************************************************************
157 
159 {
160  // prevent multiple init
161  if (!m_hCaptureWnd)
162  {
163  // init attributes and create capture window
164  m_hCaptureWnd = capCreateCaptureWindow("Capture Window", 0, 0, 0, 640, 480, NULL, 0);
165  if (!m_hCaptureWnd)
166  return false;
167 
168  // set callback function for single frame capturing
169  if (!capSetCallbackOnFrame(m_hCaptureWnd, CallbackProc))
170  {
171  DestroyWindow(m_hCaptureWnd);
172  m_hCaptureWnd = 0;
173  return false;
174  }
175  }
176 
177  // connect to driver
178  if (!capDriverConnect(m_hCaptureWnd, m_nDriverIndex))
179  {
180  DestroyWindow(m_hCaptureWnd);
181  m_hCaptureWnd = 0;
182  return false;
183  }
184 
186 
187  capOverlay(m_hCaptureWnd, FALSE);
188  capPreview(m_hCaptureWnd, FALSE);
189 
190  CAPTUREPARMS s;
191  s.dwRequestMicroSecPerFrame = 41667;
192  s.fMakeUserHitOKToCapture = FALSE;
193  s.wPercentDropForError = 10;
194  s.fYield = TRUE;
195  s.dwIndexSize = 34952;
196  s.wChunkGranularity = 0;
197  s.fUsingDOSMemory = FALSE;
198  s.wNumVideoRequested = 10;
199  s.fCaptureAudio = FALSE;
200  //s.wNumAudioRequested = 0;
201  s.vKeyAbort = VK_ESCAPE;
202  s.fAbortLeftMouse = FALSE;
203  s.fAbortRightMouse = FALSE;
204  s.fLimitEnabled = FALSE;
205  //s.wTimeLimit = 0;
206  s.fMCIControl = FALSE;
207  //s.fStepMCIDevice = FALSE;
208  //s.dwMCIStartTime = 0;
209  //s.dwMCIStopTime = 0;
210  s.fStepCaptureAt2x = FALSE;
211  s.wStepCaptureAverageFrames = 1;
212  s.dwAudioBufferSize = 0;
213  s.fDisableWriteCache = FALSE;
214  s.AVStreamMaster = AVSTREAMMASTER_NONE;
215 
216  capCaptureSetSetup(m_hCaptureWnd, &s, sizeof(CAPTUREPARMS));
217  //capCaptureSequenceNoFile(m_hCaptureWnd);
218 
219  m_bCameraOpened = true;
220 
221  return true;
222 }
223 
225 {
226  if (m_bCameraOpened)
227  {
228  //capCaptureAbort(m_hCaptureWnd);
229  //capCaptureStop(m_hCaptureWnd);
230  capDriverDisconnect(m_hCaptureWnd);
231 
232  m_nWidth = 0;
233  m_nHeight = 0;
234  m_nBitsPerPixel = 0;
235 
236  m_bCameraOpened = false;
237  }
238 }
239 
240 bool CVFWCapture::GetDriverName(int nDriverIndex, std::string &sName)
241 {
242  char szName[1000];
243  char szVersion[1000];
244 
245  if (!capGetDriverDescription(nDriverIndex, szName, sizeof(szName), szVersion, sizeof(szVersion)))
246  return false;
247 
248  sName = "";
249  sName += szName;
250 
251  return true;
252 }
253 
255 {
256  EnterCriticalSection(&critical_section);
257 
258  CAPDRIVERCAPS gCapDriverCaps;
259 
260  // get driver information
261  if (m_hCaptureWnd && capDriverGetCaps(m_hCaptureWnd, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)))
262  {
263  if (gCapDriverCaps.fHasDlgVideoFormat)
264  {
265  capDlgVideoFormat(m_hCaptureWnd);
267  }
268  }
269 
270  LeaveCriticalSection(&critical_section);
271 }
272 
274 {
275  CAPDRIVERCAPS gCapDriverCaps;
276 
277  // get driver information
278  if (m_hCaptureWnd && capDriverGetCaps(m_hCaptureWnd, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)))
279  {
280  if (gCapDriverCaps.fHasDlgVideoSource)
281  {
282  capDlgVideoSource(m_hCaptureWnd);
284  }
285  }
286 }
287 
289 {
290  EnterCriticalSection(&critical_section);
291 
292  BITMAPINFO bitmapInfo;
293 
294  if (m_hCaptureWnd && capGetVideoFormat(m_hCaptureWnd, &bitmapInfo, sizeof(BITMAPINFO)))
295  {
296  m_nWidth = bitmapInfo.bmiHeader.biWidth;
297  m_nHeight = abs(bitmapInfo.bmiHeader.biHeight);
298  m_nBitsPerPixel = bitmapInfo.bmiHeader.biBitCount;
299  m_nCompression = bitmapInfo.bmiHeader.biCompression;
300 
301  m_bFlipY = false;
302 
303  // For compressed video and YUV formats, this member is a FOURCC code, specified as a DWORD
304  // in little-endian order. For example, YUYV video has the FOURCC 'VYUY' or 0x56595559. For
305  // more information, see FOURCC Codes.
306  // For uncompressed RGB formats, the following values are possible:
307  // Value Description
308  // BI_RGB Uncompressed RGB.
309  // BI_BITFIELDS Uncompressed RGB with color masks. Valid for 16-bpp and 32-bpp bitmaps.
310  if (m_nCompression != BI_RGB && m_nCompression != BI_BITFIELDS)
311  {
312  printf("fourcc = %08x (%c%c%c%c)\n", m_nCompression, (m_nCompression >> 0) & 0xff, (m_nCompression >> 8) & 0xff, (m_nCompression >> 16) & 0xff, (m_nCompression >> 24) & 0xff);
314  }
315  else
316  {
318 
319  if (bitmapInfo.bmiHeader.biHeight > 0)
320  {
321  // image is transmitted bottom-up (vertically flipped)
322  m_bFlipY = true;
323  }
324  }
325 
326  if (pCapturedImage)
327  delete pCapturedImage;
328 
329  pCapturedImage = new CByteImage(m_nWidth, m_nHeight, m_type, true);
330  }
331 
332  LeaveCriticalSection(&critical_section);
333 }
334 
336 {
337  capGrabFrameNoStop(m_hCaptureWnd);
338 
339  EnterCriticalSection(&critical_section);
340 
341  // check if input image matches format
342  if (!m_bCameraOpened || !m_hCaptureWnd || !ppImages || !ppImages[0] || m_nWidth != ppImages[0]->width || m_nHeight != ppImages[0]->height || m_type != ppImages[0]->type)
343  {
344  LeaveCriticalSection(&critical_section);
345  return false;
346  }
347 
348  if (pCapturedImage && pCapturedImage->pixels)
349  {
350  if (pCapturedImage->type == CByteImage::eRGB24)
351  {
352  unsigned char *output = ppImages[0]->pixels;
353 
354  if (m_nCompression == BI_RGB)
355  {
356  if (m_nBitsPerPixel == 24)
357  {
358  const int nBytes = m_nWidth * m_nHeight * 3;
359  const unsigned char *input = pCapturedImage->pixels;
360 
361  for (int i = 0; i < nBytes; i += 3)
362  {
363  output[i] = input[i + 2];
364  output[i + 1] = input[i + 1];
365  output[i + 2] = input[i];
366  }
367  }
368  }
369  else if (m_nCompression == BI_BITFIELDS)
370  {
371  printf("error: BI_BITFIELDS not yet implemented\n");
372  }
373  else
374  {
375  // thanks to Paul van Niekerk
376  if (m_nCompression == BI_I420)
377  {
378  const int nBytes = m_nWidth * m_nHeight;
379  const unsigned char *inputY = pCapturedImage->pixels;
380  const unsigned char *inputU = inputY + nBytes;
381  const unsigned char *inputV = inputU + nBytes / 4;
382 
383  int i = 0;
384  for (int h = 0; h < m_nHeight; h += 1)
385  {
386  for (int w = 0; w < m_nWidth; w += 1)
387  {
388  int j = (h / 2) * (m_nWidth / 2) + (w / 2);
389  yuv2rgb(inputY[i], inputU[j], inputV[j], &output[3 * i]);
390  i += 1;
391  }
392  }
393  }
394  else if (m_nCompression == BI_YUY2)
395  {
396  const int nBytes = m_nWidth * m_nHeight * 2;
397  const unsigned char *input = pCapturedImage->pixels;
398 
399  for (int i = 0; i < nBytes; i += 4)
400  {
401  unsigned char y0 = *input++;
402  unsigned char u = *input++;
403  unsigned char y1 = *input++;
404  unsigned char v = *input++;
405 
406  yuv2rgb(y0, u, v, output);
407  output += 3;
408  yuv2rgb(y1, u, v, output);
409  output += 3;
410  }
411  }
412  }
413  }
414  else
415  ImageProcessor::CopyImage(pCapturedImage, ppImages[0]);
416  }
417 
418  LeaveCriticalSection(&critical_section);
419 
420  if (m_bFlipY)
421  ImageProcessor::FlipY(ppImages[0], ppImages[0]);
422 
423  return true;
424 }
425 
426 #undef BI_I420
427 #undef BI_YUY2
bool m_bFlipY
Definition: VFWCapture.h:104
int m_nBitsPerPixel
Definition: VFWCapture.h:97
void ShowVideoSourceDialog()
Definition: VFWCapture.cpp:273
CVFWCapture(int nDriverIndex)
Definition: VFWCapture.cpp:116
bool GetDriverName(int nDriverIndex, std::string &sName)
Definition: VFWCapture.cpp:240
int m_nWidth
Definition: VFWCapture.h:95
void CloseCamera()
Definition: VFWCapture.cpp:224
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80
CByteImage::ImageType m_type
Definition: VFWCapture.h:99
GLdouble s
Definition: glext.h:3211
void UpdateInformation()
Definition: VFWCapture.cpp:288
int m_clip[1024]
Definition: VFWCapture.h:106
CRITICAL_SECTION critical_section
Definition: VFWCapture.cpp:69
bool OpenCamera()
Definition: VFWCapture.cpp:158
static void yuv2rgb(unsigned char y, unsigned char u, unsigned char v, unsigned char *out)
Definition: VFWCapture.cpp:78
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3121
unsigned char * pixels
The pointer to the the pixels.
Definition: ByteImage.h:283
bool FlipY(const CByteImage *pInputImage, CByteImage *pOutputImage)
Flips the rows in a CByteImage vertically and writes the result to a CByteImage.
#define myClip(x)
Definition: VFWCapture.cpp:77
bool CopyImage(const CByteImage *pInputImage, CByteImage *pOutputImage, const MyRegion *pROI=0, bool bUseSameSize=false)
Copies one CByteImage to another.
HWND m_hCaptureWnd
Definition: VFWCapture.h:93
GLsizei const GLchar ** string
Definition: glext.h:3528
static CByteImage * pCapturedImage
Definition: VFWCapture.cpp:70
#define BI_I420
Definition: VFWCapture.cpp:61
GLenum GLsizei width
Definition: glext.h:3122
GLenum GLsizei GLsizei height
Definition: glext.h:3132
int m_nHeight
Definition: VFWCapture.h:96
GLenum GLenum GLenum input
Definition: glext.h:5307
ImageType type
The type of the image.
Definition: ByteImage.h:292
unsigned long m_nCompression
Definition: VFWCapture.h:98
int m_nDriverIndex
Definition: VFWCapture.h:101
GLenum GLint GLint y
Definition: glext.h:3125
const GLdouble * v
Definition: glext.h:3212
static LRESULT CALLBACK CallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
Definition: VFWCapture.cpp:94
bool CaptureImage(CByteImage **ppImages)
Definition: VFWCapture.cpp:335
void ShowVideoFormatDialog()
Definition: VFWCapture.cpp:254
#define BI_YUY2
Definition: VFWCapture.cpp:62
bool m_bCameraOpened
Definition: VFWCapture.h:102
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3571


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Mon Dec 2 2019 03:47:28