PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusWin32VideoSource2.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 /*=========================================================================
8 The following copyright notice is applicable to parts of this file:
9 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
10 All rights reserved.
11 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
12 Authors include: Danielle Pace
13 =========================================================================*/
14 
15 #include "PixelCodec.h"
16 #include "PlusConfigure.h"
17 #include "vtkObjectFactory.h"
18 #include "vtkPlusChannel.h"
19 #include "vtkPlusDataSource.h"
20 #include "vtkUnsignedCharArray.h"
22 
23 #include <ctype.h>
24 
25 // because of warnings in windows header push and pop the warning level
26 #ifdef _MSC_VER
27  #pragma warning (push, 3)
28 #endif
29 
30 #include "vtkWindows.h"
31 #include <vfw.h>
32 #include <winuser.h>
33 
34 #ifdef _MSC_VER
35  #pragma warning (pop)
36 #endif
37 
38 class vtkPlusWin32VideoSource2Internal
39 {
40 public:
41  //----------------------------------------------------------------------------
42  vtkPlusWin32VideoSource2Internal()
43  {
44  CapWnd = NULL;
45  ParentWnd = NULL;
46  BitMapInfoSize = 0;
47  BitMapInfoPtr = NULL;
48  }
49  //----------------------------------------------------------------------------
50  virtual ~vtkPlusWin32VideoSource2Internal()
51  {
52  delete [](char*)(BitMapInfoPtr);
53  BitMapInfoPtr = NULL;
54  BitMapInfoSize = 0;
55  }
56  //----------------------------------------------------------------------------
57  PlusStatus GetBitmapInfoFromCaptureDevice()
58  {
59  if (CapWnd == NULL)
60  {
61  LOG_ERROR("Cannot get bitmap info, capture window has not been created yet");
62  return PLUS_FAIL;
63  }
64  int formatSize = capGetVideoFormatSize(CapWnd);
65  if (formatSize > this->BitMapInfoSize)
66  {
67  delete []((char*)BitMapInfoPtr);
68  BitMapInfoPtr = (LPBITMAPINFO) new char[formatSize];
69  BitMapInfoSize = formatSize;
70  }
71  if (!capGetVideoFormat(CapWnd, BitMapInfoPtr, formatSize))
72  {
73  LOG_ERROR("Cannot get bitmap info from capture window");
74  return PLUS_FAIL;
75  }
76  return PLUS_SUCCESS;
77  }
78  //----------------------------------------------------------------------------
79  PlusStatus SetBitmapInfoInCaptureDevice()
80  {
81  if (!capSetVideoFormat(CapWnd, BitMapInfoPtr, BitMapInfoSize))
82  {
83  LOG_ERROR("Cannot set bitmap video format for capture window");
84  return PLUS_FAIL;
85  }
86  return PLUS_SUCCESS;
87  }
88 
89  HWND CapWnd;
90  HWND ParentWnd;
91  CAPSTATUS CapStatus;
92  CAPDRIVERCAPS CapDriverCaps;
93  CAPTUREPARMS CaptureParms;
94  LPBITMAPINFO BitMapInfoPtr;
95  int BitMapInfoSize;
96 };
97 
99 
100 #if ( _MSC_VER >= 1300 ) // Visual studio .NET
101  #pragma warning ( disable : 4311 )
102  #pragma warning ( disable : 4312 )
103  #define vtkGetWindowLong GetWindowLongPtr
104  #define vtkSetWindowLong SetWindowLongPtr
105  #define vtkGWL_USERDATA GWLP_USERDATA
106 #else // regular Visual studio
107  #define vtkGetWindowLong GetWindowLong
108  #define vtkSetWindowLong SetWindowLong
109  #define vtkGWL_USERDATA GWL_USERDATA
110 #endif //
111 
112 //----------------------------------------------------------------------------
114  : Internal(new vtkPlusWin32VideoSource2Internal)
115  , WndClassName(NULL)
116  , Preview(0)
117  , FrameIndex(0)
118 {
120 
121  // No need for StartThreadForInternalUpdates, as we are notified about each new frame through a callback function
122 }
123 
124 //----------------------------------------------------------------------------
126 {
128 
129  delete this->Internal;
130  this->Internal = NULL;
131 }
132 
133 //----------------------------------------------------------------------------
134 void vtkPlusWin32VideoSource2::PrintSelf(ostream& os, vtkIndent indent)
135 {
136  this->Superclass::PrintSelf(os, indent);
137 
138  os << indent << "Preview: " << (this->Preview ? "On\n" : "Off\n");
139 }
140 
141 //----------------------------------------------------------------------------
142 LONG FAR PASCAL vtkPlusWin32VideoSource2WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
143 {
145  switch (message)
146  {
147  case WM_MOVE:
148  LOG_TRACE("WM_MOVE");
149  break;
150  case WM_SIZE:
151  LOG_TRACE("WM_SIZE");
152  break;
153  case WM_DESTROY:
154  LOG_TRACE("WM_DESTROY");
155  self->OnParentWndDestroy();
156  break;
157  case WM_CLOSE:
158  LOG_TRACE("WM_CLOSE");
159  self->PreviewOff();
160  return 0;
161  }
162  return DefWindowProc(hwnd, message, wParam, lParam);
163 }
164 
165 //----------------------------------------------------------------------------
166 LRESULT PASCAL vtkPlusWin32VideoSource2CapControlProc(HWND hwndC, int nState)
167 {
168  vtkPlusWin32VideoSource2* self = (vtkPlusWin32VideoSource2*)(capGetUserData(hwndC));
169  if (nState == CONTROLCALLBACK_PREROLL)
170  {
171  LOG_TRACE("controlcallback preroll");
172  }
173  else if (nState == CONTROLCALLBACK_CAPTURING)
174  {
175  LOG_TRACE("controlcallback capturing");
176  }
177  return TRUE;
178 }
179 
180 //----------------------------------------------------------------------------
181 LRESULT PASCAL vtkPlusWin32VideoSource2CallbackProc(HWND hwndC, LPVIDEOHDR lpVideoHeader)
182 {
183  vtkPlusWin32VideoSource2* self = (vtkPlusWin32VideoSource2*)(capGetUserData(hwndC));
184  self->AddFrameToBuffer(lpVideoHeader);
185  return 0;
186 }
187 
188 //----------------------------------------------------------------------------
189 // this callback is left in for debug purposes
190 LRESULT PASCAL vtkPlusWin32VideoSource2StatusCallbackProc(HWND vtkNotUsed(hwndC), int nID, LPCSTR vtkNotUsed(lpsz))
191 {
192  //vtkPlusWin32VideoSource2 *self = (vtkPlusWin32VideoSource2 *)(capGetUserData(hwndC));
193  if (nID == IDS_CAP_BEGIN)
194  {
195  LOG_TRACE("start of capture");
196  }
197  if (nID == IDS_CAP_END)
198  {
199  LOG_TRACE("end of capture");
200  }
201  return 1;
202 }
203 
204 //----------------------------------------------------------------------------
205 LRESULT PASCAL vtkPlusWin32VideoSource2ErrorCallbackProc(HWND hwndC, int ErrID, LPSTR lpErrorText)
206 {
207  if (ErrID)
208  {
209  LOG_ERROR("Video for Windows error: #" << ErrID);
210  }
211  return 1;
212 }
213 
214 //----------------------------------------------------------------------------
216 {
217  if (this->GetConnected())
218  {
219  // already connected
220  return PLUS_SUCCESS;
221  }
222 
223  // get necessary process info
224  HINSTANCE hinstance = GetModuleHandle(NULL);
225 
226  // set up a class for the main window
227  WNDCLASS wc;
228  wc.lpszClassName = this->WndClassName;
229  wc.hInstance = hinstance;
230  wc.lpfnWndProc = reinterpret_cast<WNDPROC>(&vtkPlusWin32VideoSource2WinProc);
231  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
232  wc.hIcon = NULL;
233  wc.lpszMenuName = NULL;
234  wc.hbrBackground = NULL;
235  wc.style = CS_HREDRAW | CS_VREDRAW;
236  wc.cbClsExtra = sizeof(void*);
237  wc.cbWndExtra = 0;
238 
239  std::string windowNameStr;
240  bool registrationSuccessful = false;
241  const int MAX_WINDOW_CLASS_REGISTRATION_ATTEMPTS = 32;
242  for (int i = 1; i <= MAX_WINDOW_CLASS_REGISTRATION_ATTEMPTS; i++)
243  {
244  if (RegisterClass(&wc))
245  {
246  SetWndClassName(wc.lpszClassName);
247  registrationSuccessful = true;
248  break;
249  }
250  // try with a slightly different name at each registration attempt
251  std::ostringstream windowName;
252  windowName << "VTKVideo " << i << std::ends;
253  windowNameStr = windowName.str();
254  wc.lpszClassName = windowNameStr.c_str();
255  }
256  if (!registrationSuccessful)
257  {
258  LOG_ERROR("Initialize: failed to register VTKVideo class (" << GetLastError() << ")");
259  return PLUS_FAIL;
260  }
261 
262  DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
263 
264  if (this->Preview)
265  {
266  style |= WS_VISIBLE;
267  }
268 
269  // set up the parent window, but don't show it
270  vtkPlusDataSource* aSource(NULL);
271  if (this->GetFirstVideoSource(aSource) != PLUS_SUCCESS)
272  {
273  LOG_ERROR("Unable to retrieve the video source in the Win32Video device.");
274  return PLUS_FAIL;
275  }
276  FrameSizeType frameSize = aSource->GetInputFrameSize();
277 
278  this->Internal->ParentWnd = CreateWindow(this->WndClassName, "Plus video capture window", style, 0, 0,
279  frameSize[0] + 2 * GetSystemMetrics(SM_CXFIXEDFRAME),
280  frameSize[1] + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYSIZE),
281  NULL, NULL, hinstance, NULL);
282 
283  if (!this->Internal->ParentWnd)
284  {
285  LOG_ERROR("Initialize: failed to create window (" << GetLastError() << ")");
286  return PLUS_FAIL;
287  }
288 
289  // set the user data to 'this'
290  vtkSetWindowLong(this->Internal->ParentWnd, vtkGWL_USERDATA, (LONG_PTR)this);
291 
292  // Create the capture window
293  this->Internal->CapWnd = capCreateCaptureWindow("Capture", WS_CHILD | WS_VISIBLE, 0, 0,
294  frameSize[0], frameSize[1], this->Internal->ParentWnd, 1);
295 
296  if (!this->Internal->CapWnd)
297  {
298  LOG_ERROR("Initialize: failed to create capture window (" << GetLastError() << ")");
299  this->ReleaseSystemResources();
300  return PLUS_FAIL;
301  }
302 
303  // connect to the driver
304  if (!capDriverConnect(this->Internal->CapWnd, 0))
305  {
306  LOG_ERROR("Initialize: couldn't connect to driver (" << GetLastError() << ")");
307  this->ReleaseSystemResources();
308  return PLUS_FAIL;
309  }
310 
311  capDriverGetCaps(this->Internal->CapWnd, &this->Internal->CapDriverCaps, sizeof(CAPDRIVERCAPS));
312 
313  // set up the video capture format
314  this->Internal->GetBitmapInfoFromCaptureDevice();
315  //this->Internal->BitMapInfoPtr->bmiHeader.biWidth = frameSize[0];
316  //this->Internal->BitMapInfoPtr->bmiHeader.biHeight = frameSize[1];
317  if (this->Internal->SetBitmapInfoInCaptureDevice() != PLUS_SUCCESS)
318  {
319  LOG_ERROR("Failed to set requested frame size in the capture device");
320  this->ReleaseSystemResources();
321  return PLUS_FAIL;
322  }
323 
324  int width = this->Internal->BitMapInfoPtr->bmiHeader.biWidth;
325  int height = this->Internal->BitMapInfoPtr->bmiHeader.biHeight;
326  this->ReleaseSystemResources();
327  this->Internal->ParentWnd = CreateWindow(this->WndClassName, "Plus video capture window", style, 0, 0,
328  width + 2 * GetSystemMetrics(SM_CXFIXEDFRAME),
329  height + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYSIZE),
330  NULL, NULL, hinstance, NULL);
331 
332  if (!this->Internal->ParentWnd)
333  {
334  LOG_ERROR("Initialize: failed to create window (" << GetLastError() << ")");
335  return PLUS_FAIL;
336  }
337 
338  // set the user data to 'this'
339  vtkSetWindowLong(this->Internal->ParentWnd, vtkGWL_USERDATA, (LONG_PTR)this);
340 
341  // Create the capture window
342  this->Internal->CapWnd = capCreateCaptureWindow("Capture", WS_CHILD | WS_VISIBLE, 0, 0,
343  frameSize[0], frameSize[1], this->Internal->ParentWnd, 1);
344 
345  if (!this->Internal->CapWnd)
346  {
347  LOG_ERROR("Initialize: failed to create capture window (" << GetLastError() << ")");
348  this->ReleaseSystemResources();
349  return PLUS_FAIL;
350  }
351 
352  // connect to the driver
353  if (!capDriverConnect(this->Internal->CapWnd, 0))
354  {
355  LOG_ERROR("Initialize: couldn't connect to driver (" << GetLastError() << ")");
356  this->ReleaseSystemResources();
357  return PLUS_FAIL;
358  }
359 
360  capDriverGetCaps(this->Internal->CapWnd, &this->Internal->CapDriverCaps, sizeof(CAPDRIVERCAPS));
361 
362  // set the capture parameters
363  capCaptureGetSetup(this->Internal->CapWnd, &this->Internal->CaptureParms, sizeof(CAPTUREPARMS));
364 
365  if (this->AcquisitionRate > 0)
366  {
367  this->Internal->CaptureParms.dwRequestMicroSecPerFrame = int(1000000 / this->AcquisitionRate);
368  }
369  else
370  {
371  this->Internal->CaptureParms.dwRequestMicroSecPerFrame = 0;
372  }
373 
374  this->Internal->CaptureParms.fMakeUserHitOKToCapture = FALSE;
375  this->Internal->CaptureParms.fYield = 1;
376  this->Internal->CaptureParms.fCaptureAudio = FALSE;
377  this->Internal->CaptureParms.vKeyAbort = 0x00;
378  this->Internal->CaptureParms.fAbortLeftMouse = FALSE;
379  this->Internal->CaptureParms.fAbortRightMouse = FALSE;
380  this->Internal->CaptureParms.fLimitEnabled = FALSE;
381  this->Internal->CaptureParms.wNumAudioRequested = 0;
382  this->Internal->CaptureParms.wPercentDropForError = 100;
383  this->Internal->CaptureParms.dwAudioBufferSize = 0;
384  this->Internal->CaptureParms.AVStreamMaster = AVSTREAMMASTER_NONE;
385 
386  if (!capCaptureSetSetup(this->Internal->CapWnd, &this->Internal->CaptureParms, sizeof(CAPTUREPARMS)))
387  {
388  LOG_ERROR("Initialize: setup of capture parameters failed (" << GetLastError() << ")");
389  this->ReleaseSystemResources();
390  return PLUS_FAIL;
391  }
392 
393  // set user data for callbacks
394  if (!capSetUserData(this->Internal->CapWnd, (LONG_PTR)this))
395  {
396  LOG_ERROR("Initialize: couldn't set user data for callback (" << GetLastError() << ")");
397  this->ReleaseSystemResources();
398  return PLUS_FAIL;
399  }
400 
401  // install the callback to precisely time beginning of grab
402  if (!capSetCallbackOnCapControl(this->Internal->CapWnd, &vtkPlusWin32VideoSource2CapControlProc))
403  {
404  LOG_ERROR("Initialize: couldn't set control callback (" << GetLastError() << ")");
405  this->ReleaseSystemResources();
406  return PLUS_FAIL;
407  }
408 
409  // install the callback to copy frames into the buffer on sync grabs
410  if (!capSetCallbackOnFrame(this->Internal->CapWnd, &vtkPlusWin32VideoSource2CallbackProc))
411  {
412  LOG_ERROR("Initialize: couldn't set frame callback (" << GetLastError() << ")");
413  this->ReleaseSystemResources();
414  return PLUS_FAIL;
415  }
416  // install the callback to copy frames into the buffer on stream grabs
417  if (!capSetCallbackOnVideoStream(this->Internal->CapWnd, &vtkPlusWin32VideoSource2CallbackProc))
418  {
419  LOG_ERROR("Initialize: couldn't set stream callback (" << GetLastError() << ")");
420  this->ReleaseSystemResources();
421  return PLUS_FAIL;
422  }
423  // install the callback to get info on start/end of streaming
424  if (!capSetCallbackOnStatus(this->Internal->CapWnd, &vtkPlusWin32VideoSource2StatusCallbackProc))
425  {
426  LOG_ERROR("Initialize: couldn't set status callback (" << GetLastError() << ")");
427  this->ReleaseSystemResources();
428  return PLUS_FAIL;
429  }
430  // install the callback to send messages to user
431  if (!capSetCallbackOnError(this->Internal->CapWnd, &vtkPlusWin32VideoSource2ErrorCallbackProc))
432  {
433  LOG_ERROR("Initialize: couldn't set error callback (" << GetLastError() << ")");
434  this->ReleaseSystemResources();
435  return PLUS_FAIL;
436  }
437 
438  capOverlay(this->Internal->CapWnd, TRUE);
439 
440  // update framebuffer again to reflect any changes which
441  // might have occurred
442  this->UpdateFrameBuffer();
443 
444  return PLUS_SUCCESS;
445 }
446 
448 {
449  if (this->Internal->CapWnd)
450  {
451  LOG_DEBUG("capDriverDisconnect(this->Internal->CapWnd)");
452  capDriverDisconnect(this->Internal->CapWnd);
453  LOG_DEBUG("DestroyWindow(this->Internal->CapWnd)");
454  DestroyWindow(this->Internal->CapWnd);
455  this->Internal->CapWnd = NULL;
456  }
457  if (this->WndClassName != NULL && this->WndClassName[0] != '\0')
458  {
459  // window class name is valid
460  UnregisterClass(this->WndClassName, GetModuleHandle(NULL));
461  SetWndClassName("");
462  }
463 
464  return PLUS_SUCCESS;
465 }
466 
467 //----------------------------------------------------------------------------
469 {
470  if (this->Preview == showPreview)
471  {
472  return;
473  }
474 
475  this->Preview = showPreview;
476 
477  if (GetConnected())
478  {
479  if (this->Internal->CapWnd == NULL || this->Internal->ParentWnd == NULL)
480  {
481  LOG_ERROR("Capture windows have not been intialized");
482  return;
483  }
484  if (this->Preview)
485  {
486  ShowWindow(this->Internal->ParentWnd, SW_SHOWNORMAL);
487  }
488  else
489  {
490  ShowWindow(this->Internal->ParentWnd, SW_HIDE);
491  }
492  }
493  this->Modified();
494 }
495 
496 //----------------------------------------------------------------------------
498 {
499  // destruction of ParentWnd causes OnParentWndDestroy to be called
500  if (this->Internal->ParentWnd)
501  {
502  DestroyWindow(this->Internal->ParentWnd);
503  }
504 }
505 
506 //----------------------------------------------------------------------------
508 {
509  Disconnect();
510  this->Internal->ParentWnd = NULL;
511 }
512 
513 //----------------------------------------------------------------------------
515 {
516  int inputCompression = this->Internal->BitMapInfoPtr->bmiHeader.biCompression;
517  if (!PixelCodec::IsConvertToGraySupported(inputCompression))
518  {
519  LOG_ERROR("AddFrameToBuffer: video compression mode " << PixelCodec::GetCompressionModeAsString(inputCompression) << ": can't grab");
520  return PLUS_FAIL;
521  }
522 
523  LOG_TRACE("Grabbed");
524 
525  LPVIDEOHDR lpVHdr = static_cast<LPVIDEOHDR>(lpVideoHeader);
526 
527  // the VIDEOHDR has the following contents, for quick ref:
528  //
529  // lpData pointer to locked data buffer
530  // dwBufferLength Length of data buffer
531  // dwBytesUsed Bytes actually used
532  // dwTimeCaptured Milliseconds from start of stream
533  // dwUser for client's use
534  // dwFlags assorted flags (see VFW.H)
535  // dwReserved[4] reserved for driver
536 
537  unsigned char* inputPixelsPtr = lpVHdr->lpData;
538 
539  FrameSizeType outputFrameSize;
540  if (this->UncompressedVideoFrame.GetFrameSize(outputFrameSize) != PLUS_SUCCESS)
541  {
542  LOG_ERROR("Unable to retrieve frame size.");
543  return PLUS_FAIL;
544  }
545 
546  if (PixelCodec::ConvertToGray(inputCompression, outputFrameSize[0], outputFrameSize[1], inputPixelsPtr, (unsigned char*)this->UncompressedVideoFrame.GetScalarPointer()) != PLUS_SUCCESS)
547  {
548  LOG_ERROR("Error while decoding the grabbed image");
549  return PLUS_FAIL;
550  }
551 
552  this->FrameIndex++;
553  vtkPlusDataSource* aSource(NULL);
554  if (this->GetFirstVideoSource(aSource) != PLUS_SUCCESS)
555  {
556  LOG_ERROR("Unable to retrieve the video source in the Win32Video device.");
557  return PLUS_FAIL;
558  }
559  double indexTime = aSource->GetStartTime() + 0.001 * lpVHdr->dwTimeCaptured;
560  this->UncompressedVideoFrame.SetImageOrientation(aSource->GetInputImageOrientation());
561  PlusStatus status = aSource->AddItem(&this->UncompressedVideoFrame, this->FrameIndex, indexTime, indexTime);
562 
563  this->Modified();
564  return status;
565 }
566 
567 //----------------------------------------------------------------------------
569 {
570  // just request the grab, the callback does the rest
571  if (!capGrabFrameNoStop(this->Internal->CapWnd))
572  {
573  LOG_ERROR("Initialize: failed to request a single frame grab (" << GetLastError() << ")");
574  return PLUS_FAIL;
575  }
576  return PLUS_SUCCESS;
577 }
578 
579 //----------------------------------------------------------------------------
581 {
582  if (!capCaptureSequenceNoFile(this->Internal->CapWnd))
583  {
584  LOG_ERROR("Initialize: failed to request continuous frame grabbing (" << GetLastError() << ")");
585  return PLUS_FAIL;
586  }
587  this->FrameIndex = 0;
588  //double startTime = vtkIGSIOAccurateTimer::GetSystemTime();
589  //this->Buffer->SetStartTime(startTime);
590  return PLUS_SUCCESS;
591 }
592 
593 //----------------------------------------------------------------------------
595 {
596  if (!capCaptureStop(this->Internal->CapWnd))
597  {
598  LOG_ERROR("Initialize: failed to request continuous frame grabbing (" << GetLastError() << ")");
599  return PLUS_FAIL;
600  }
601  return PLUS_SUCCESS;
602 }
603 
604 //----------------------------------------------------------------------------
606 {
607  if (!GetConnected())
608  {
609  LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed, need to connect to the device first");
610  return PLUS_FAIL;
611  }
612 
613  //if (!this->Internal->CapDriverCaps.fHasDlgVideoFormat)
614  // {
615  // LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed, the video device has no Format dialog.");
616  // return PLUS_FAIL;
617  // }
618 
619  capGetStatus(this->Internal->CapWnd, &this->Internal->CapStatus, sizeof(CAPSTATUS));
620  if (this->Internal->CapStatus.fCapturingNow)
621  {
622  LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed, can't alter video format while grabbing");
623  return PLUS_FAIL;
624  }
625 
626  int success = capDlgVideoFormat(this->Internal->CapWnd);
627  if (!success)
628  {
629  LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed (" << GetLastError() << ")");
630  return PLUS_FAIL;
631  }
632  this->UpdateFrameBuffer();
633  return PLUS_SUCCESS;
634 }
635 
636 //----------------------------------------------------------------------------
638 {
639  if (!GetConnected())
640  {
641  LOG_ERROR("vtkPlusWin32VideoSource2::VideoSourceDialog failed, need to connect to the device first");
642  return PLUS_FAIL;
643  }
644 
645  //if (!this->Internal->CapDriverCaps.fHasDlgVideoSource)
646  // {
647  // LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed, the video device has no Source dialog.");
648  // return PLUS_FAIL;
649  // }
650 
651  capGetStatus(this->Internal->CapWnd, &this->Internal->CapStatus, sizeof(CAPSTATUS));
652  if (this->Internal->CapStatus.fCapturingNow)
653  {
654  LOG_ERROR("vtkPlusWin32VideoSource2::VideoFormatDialog failed, can't alter video source while grabbing");
655  return PLUS_FAIL;
656  }
657 
658  int success = capDlgVideoSource(this->Internal->CapWnd);
659  if (!success)
660  {
661  LOG_ERROR("vtkPlusWin32VideoSource2::VideoSourceDialog failed (" << GetLastError() << ")");
662  return PLUS_FAIL;
663  }
664  return this->UpdateFrameBuffer();
665 }
666 
667 //----------------------------------------------------------------------------
668 PlusStatus vtkPlusWin32VideoSource2::SetFrameSize(const FrameSizeType& frameSize)
669 {
670  vtkPlusDataSource* aSource(NULL);
671  if (this->GetFirstVideoSource(aSource) != PLUS_SUCCESS)
672  {
673  LOG_ERROR(this->GetDeviceId() << ": Unable to retrieve video source.");
674  return PLUS_FAIL;
675  }
676  if (this->Superclass::SetInputFrameSize(*aSource, frameSize[0], frameSize[1], 1) != PLUS_SUCCESS)
677  {
678  return PLUS_FAIL;
679  }
680  if (this->GetConnected())
681  {
682  // set up the video capture format
683  this->Internal->GetBitmapInfoFromCaptureDevice();
684  this->Internal->BitMapInfoPtr->bmiHeader.biWidth = frameSize[0];
685  this->Internal->BitMapInfoPtr->bmiHeader.biHeight = frameSize[1];
686  if (this->Internal->SetBitmapInfoInCaptureDevice() != PLUS_SUCCESS)
687  {
688  LOG_ERROR("Failed to set requested frame size in the capture device");
689  return PLUS_FAIL;
690  }
691  }
692  return PLUS_SUCCESS;
693 }
694 
695 //----------------------------------------------------------------------------
697 {
698  if (rate == this->AcquisitionRate)
699  {
700  // no change
701  return PLUS_SUCCESS;
702  }
703 
704  this->AcquisitionRate = rate;
705 
706  if (GetConnected())
707  {
708  capCaptureGetSetup(this->Internal->CapWnd, &this->Internal->CaptureParms, sizeof(CAPTUREPARMS));
709  if (this->AcquisitionRate > 0)
710  {
711  this->Internal->CaptureParms.dwRequestMicroSecPerFrame = int(1000000 / this->AcquisitionRate);
712  }
713  else
714  {
715  this->Internal->CaptureParms.dwRequestMicroSecPerFrame = 0;
716  }
717  capCaptureSetSetup(this->Internal->CapWnd, &this->Internal->CaptureParms, sizeof(CAPTUREPARMS));
718  }
719 
720  this->Modified();
721  return PLUS_SUCCESS;
722 }
723 
724 //----------------------------------------------------------------------------
726 {
727  // convert color format to number of scalar components
728  unsigned int numberOfScalarComponents = 0;
729  switch (format)
730  {
731  case VTK_RGBA:
732  numberOfScalarComponents = 4;
733  break;
734  case VTK_RGB:
735  numberOfScalarComponents = 3;
736  break;
737  case VTK_LUMINANCE:
738  numberOfScalarComponents = 1;
739  break;
740  default:
741  numberOfScalarComponents = 0;
742  LOG_ERROR("SetOutputFormat: Unrecognized color format.");
743  return PLUS_FAIL;
744  }
745 
746  if (numberOfScalarComponents != 1)
747  {
748  LOG_ERROR("Currently only 1 component image output is supported. Requested " << numberOfScalarComponents << " components");
749  return PLUS_FAIL;
750  }
751 
752  vtkPlusDataSource* aSource(NULL);
753  for (ChannelContainerIterator it = this->OutputChannels.begin(); it != this->OutputChannels.end(); ++it)
754  {
755  if ((*it)->GetVideoSource(aSource) != PLUS_SUCCESS)
756  {
757  LOG_ERROR("Unable to retrieve the video source in the win32video device on channel " << (*it)->GetChannelId());
758  return PLUS_FAIL;
759  }
760  else
761  {
762  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
763  }
764  }
765 
766  if (this->GetConnected())
767  {
768  // set up the video capture format
769  this->Internal->GetBitmapInfoFromCaptureDevice();
770  // TODO: update this->Internal->BitMapInfoPtr->bmiHeader
771  if (this->Internal->SetBitmapInfoInCaptureDevice() != PLUS_SUCCESS)
772  {
773  LOG_ERROR("Failed to set requested frame size in the capture device");
774  return PLUS_FAIL;
775  }
776  }
777  return PLUS_SUCCESS;
778 }
779 
780 //----------------------------------------------------------------------------
782 {
783  // get the real video format
784  this->Internal->GetBitmapInfoFromCaptureDevice();
785 
786  unsigned int width(this->Internal->BitMapInfoPtr->bmiHeader.biWidth);
787  unsigned int height(this->Internal->BitMapInfoPtr->bmiHeader.biHeight);
788  igsioCommon::VTKScalarPixelType pixelType(VTK_UNSIGNED_CHAR); // always convert output to 8-bit grayscale
789  unsigned int numberOfScalarComponents = 1;
790 
791  vtkPlusDataSource* aSource(NULL);
792  if (this->GetFirstVideoSource(aSource) != PLUS_SUCCESS)
793  {
794  LOG_ERROR("Unable to access video source in vtkPlusWin32VideoSource2. Critical failure.");
795  return PLUS_FAIL;
796  }
797  aSource->SetInputFrameSize(width, height, 1);
798  aSource->SetPixelType(pixelType);
799  aSource->SetNumberOfScalarComponents(numberOfScalarComponents);
800 
801  FrameSizeType frameSize = {width, height, 1};
802  this->UncompressedVideoFrame.AllocateFrame(frameSize, pixelType, numberOfScalarComponents);
803 
804  return PLUS_SUCCESS;
805 }
806 
807 //----------------------------------------------------------------------------
808 
810 {
811  if (this->OutputChannels.size() > 1)
812  {
813  LOG_WARNING("Win32VideoSource is expecting one output channel and there are " << this->OutputChannels.size() << " channels. First output channel will be used.");
814  return PLUS_FAIL;
815  }
816 
817  if (this->OutputChannels.size() == 0)
818  {
819  LOG_ERROR("No output channels defined for win32 video source. Cannot proceed.");
820  this->CorrectlyConfigured = false;
821  return PLUS_FAIL;
822  }
823 
824  return PLUS_SUCCESS;
825 }
virtual PlusStatus SetOutputFormat(int format)
virtual PlusStatus SetInputFrameSize(vtkPlusDataSource &aSource, unsigned int x, unsigned int y, unsigned int z)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
#define vtkSetWindowLong
virtual PlusStatus InternalStopRecording()
int
Definition: phidget22.h:3069
LRESULT PASCAL vtkPlusWin32VideoSource2CapControlProc(HWND hwndC, int nState)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
const CHAR * LPCSTR
Definition: ATC3DGm.h:444
Video-for-Windows video digitizer.
virtual PlusStatus SetAcquisitionRate(double rate)
virtual std::string GetDeviceId() const
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
LRESULT PASCAL vtkPlusWin32VideoSource2ErrorCallbackProc(HWND hwndC, int ErrID, LPSTR lpErrorText)
static bool IsConvertToGraySupported(int inputCompression)
Definition: PixelCodec.h:67
bool RequireImageOrientationInConfiguration
for i
double AcquisitionRate
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
PlusStatus GetFirstVideoSource(vtkPlusDataSource *&anImage)
virtual double GetStartTime()
LRESULT PASCAL vtkPlusWin32VideoSource2StatusCallbackProc(HWND vtkNotUsed(hwndC), int nID, LPCSTR vtkNotUsed(lpsz))
virtual PlusStatus Disconnect()
unsigned long DWORD
Definition: ATC3DGm.h:451
#define FALSE
Definition: ATC3DGm.h:220
LONG FAR PASCAL vtkPlusWin32VideoSource2WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
virtual PlusStatus SetFrameSize(const FrameSizeType &frameSize)
static std::string GetCompressionModeAsString(int inputCompression)
Definition: PixelCodec.h:103
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
virtual PlusStatus InternalDisconnect()
PlusStatus AddFrameToBuffer(void *lpVideoHeader)
virtual PlusStatus InternalStartRecording()
PhidgetLCD_Font int * width
Definition: phidget22.h:4275
#define vtkGetWindowLong
LRESULT PASCAL vtkPlusWin32VideoSource2CallbackProc(HWND hwndC, LPVIDEOHDR lpVideoHeader)
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
int VTKScalarPixelType
Definition: PlusCommon.h:55
static PlusStatus ConvertToGray(int inputCompression, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:146
PhidgetLCD_Font int int * height
Definition: phidget22.h:4275
virtual int GetConnected() const
vtkStandardNewMacro(vtkPlusWin32VideoSource2)
ChannelContainer OutputChannels
PlusStatus SetNumberOfScalarComponents(unsigned int numberOfScalarComponents)
#define TRUE
Definition: ATC3DGm.h:219
const char * message
Definition: phidget22.h:2457
ChannelContainer::iterator ChannelContainerIterator
Definition: vtkPlusDevice.h:36
FrameSizeType GetInputFrameSize() const
virtual void SetWndClassName(const char *)
#define vtkGWL_USERDATA
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
vtkPlusWin32VideoSource2Internal * Internal
bool CorrectlyConfigured
Interface to a 3D positioning tool, video source, or generalized data stream.