PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusNVidiaDVPVideoSourceWin32.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 // Plus includes
8 #include "PlusConfigure.h"
9 #include "vtkPlusNvidiaDVPVideoSourceWin32.h"
10 #include "vtkPlusDataSource.h"
11 
12 // VTK includes
13 #include <vtkObjectFactory.h>
14 
15 // NVidia DVP includes
16 #include <DVPAPI.h>
17 #include <dvpapi_gl.h>
18 #include "nvGPUutil.h"
19 #include "glExtensions.h"
20 
21 // NV-API device control API
22 #include <nvapi.h>
23 
24 //----------------------------------------------------------------------------
25 
27 
28 //----------------------------------------------------------------------------
30  : FrameNumber(0)
31  , EnableGPUCPUCopy(false)
32  , VideoSize( { 0, 0, 1 })
33 {
34  // No callback function provided by the device, so the data capture thread will be used to poll the hardware and add new items to the buffer
35  this->StartThreadForInternalUpdates = true;
36  this->AcquisitionRate = 30;
37 }
38 
39 //----------------------------------------------------------------------------
41 {
42  if (this->Connected)
43  {
44  this->Disconnect();
45  }
46 }
47 
48 //----------------------------------------------------------------------------
49 void vtkPlusNvidiaDVPVideoSource::PrintSelf(ostream& os, vtkIndent indent)
50 {
51  this->Superclass::PrintSelf(os, indent);
52 }
53 
54 //----------------------------------------------------------------------------
56 {
57  LOG_TRACE("vtkPlusPhilips3DProbeVideoSource::InternalConnect");
58 
60  if (NvGPU == nullptr)
61  {
62  LOG_ERROR("Unable to retrieve NvGPU.");
63  return PLUS_FAIL;
64  }
65 
66  if (SetupSDIDevices() == E_FAIL)
67  {
68  return PLUS_FAIL;
69  }
70 
71  SetupGL();
72 
73  if (StartSDIPipeline() == E_FAIL)
74  {
75  return PLUS_FAIL;
76  }
77 
78  CPUFrame = new unsigned char[NvSDIin.GetBufferObjectPitch(0) * VideoSize[1]];
79 
80  return PLUS_SUCCESS;
81 }
82 
83 //----------------------------------------------------------------------------
85 {
86  LOG_TRACE("vtkPlusNvidiaDVPVideoSource::InternalDisconnect");
87 
88  Shutdown();
89 
90  delete [] CPUFrame;
91  CPUFrame = nullptr;
92 
93  NvGPU = nullptr;
94 
95  return PLUS_SUCCESS;
96 }
97 
98 //-----------------------------------------------------------------------------
100 {
101  CaptureVideo();
102 
103  if (EnableGPUCPUCopy)
104  {
105  CopyGPUToCPU();
106  if (OutputDataSource->AddItem((void*)CPUFrame,
109  VTK_UNSIGNED_CHAR, // TODO : scalar type from nvidia video format
110  1, // TODO : num components from nvidia video format
111  US_IMG_BRIGHTNESS, // TODO : img type from nvidia video format
112  0,
113  this->FrameNumber) != PLUS_SUCCESS)
114  {
115  LOG_ERROR("Unable to capture frame from SDI capture.");
116  return PLUS_FAIL;
117  }
118  }
119 
120  return PLUS_SUCCESS;
121 }
122 
123 //-----------------------------------------------------------------------------
124 PlusStatus vtkPlusNvidiaDVPVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
125 {
126  LOG_TRACE("vtkPlusNvidiaDVPVideoSource::ReadConfiguration");
127  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
128 
129  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(EnableGPUCPUCopy, deviceConfig);
130 
131  int numGPUs;
132  // Note, this function enumerates GPUs which are both CUDA & GLAffinity capable (i.e. newer Quadros)
133  numGPUs = CNvGpuTopology::Instance().GetNumGpu();
134 
135  if (numGPUs <= 0)
136  {
137  LOG_ERROR("Unable to obtain system GPU topology.");
138  return PLUS_FAIL;
139  }
140 
141  int numCaptureDevices = CNvSDIinTopology::Instance().GetNumDevice();
142 
143  if (numCaptureDevices <= 0)
144  {
145  LOG_ERROR("Unable to obtain system Capture topology.");
146  return PLUS_FAIL;
147  }
148 
149  // Set the defaults for all the relevant options
150  NvOptions.dualLink = false;
151  NvOptions.expansionEnable = false;
152  NvOptions.sampling = NVVIOCOMPONENTSAMPLING_422;
156  NvOptions.console = false;
157  NvOptions.numFrames = 0;
158  NvOptions.log = false;
159  NvOptions.repeat = false;
160  NvOptions.fps = false;
161  NvOptions.videoInfo = false;
162 
163  // Get framelock flag
164  if (deviceConfig->GetAttribute("Framelock") != NULL)
165  {
166  NvOptions.frameLock = false;
167  if (STRCASECMP(deviceConfig->GetAttribute("Framelock"), "TRUE") == 0)
168  {
169  NvOptions.frameLock = true;
170  }
171  }
172 
173  // Set blocking flag
174  if (deviceConfig->GetAttribute("Blocking") != NULL)
175  {
176  NvOptions.block = false;
177  if (STRCASECMP(deviceConfig->GetAttribute("Blocking"), "TRUE") == 0)
178  {
179  NvOptions.block = true;
180  }
181  }
182 
183  // Set FSAA flag
184  if (deviceConfig->GetAttribute("FSAA") != NULL)
185  {
186  NvOptions.fsaa = atoi(deviceConfig->GetAttribute("FSAA"));
187  }
188 
189  // Set frame/field enum
190  if (deviceConfig->GetAttribute("Field") != NULL)
191  {
192  NvOptions.field = false;
193  if (STRCASECMP(deviceConfig->GetAttribute("Field"), "TRUE") == 0)
194  {
195  NvOptions.field = true;
196  }
197  }
198 
199  // Colorspace conversion scale vector
200  if (deviceConfig->GetAttribute("ConversionScaleFactor") != NULL)
201  {
202  double tmpValue[3];
203  if (deviceConfig->GetVectorAttribute("ConversionScaleFactor", 3, tmpValue) == 3)
204  {
205  NvOptions.cscScale[0] = tmpValue[0];
206  NvOptions.cscScale[1] = tmpValue[1];
207  NvOptions.cscScale[2] = tmpValue[2];
208  }
209  }
210 
211  // Colorspace conversion offset vector
212  if (deviceConfig->GetAttribute("ConversionOffsetVector") != NULL)
213  {
214  double tmpValue[3];
215  if (deviceConfig->GetVectorAttribute("ConversionOffsetVector", 3, tmpValue) == 3)
216  {
217  NvOptions.cscOffset[0] = tmpValue[0];
218  NvOptions.cscOffset[1] = tmpValue[1];
219  NvOptions.cscOffset[2] = tmpValue[2];
220  }
221  }
222 
223  // Colorspace conversion matrix
224  if (deviceConfig->GetAttribute("ConversionMatrix") != NULL)
225  {
226  float tmpValue[9];
227  if (deviceConfig->GetVectorAttribute("ConversionMatrix", 9, tmpValue) == 9)
228  {
229  NvOptions.cscMatrix[0][0] = tmpValue[0];
230  NvOptions.cscMatrix[0][1] = tmpValue[1];
231  NvOptions.cscMatrix[0][2] = tmpValue[2];
232 
233  NvOptions.cscMatrix[1][0] = tmpValue[3];
234  NvOptions.cscMatrix[1][1] = tmpValue[4];
235  NvOptions.cscMatrix[1][2] = tmpValue[5];
236 
237  NvOptions.cscMatrix[2][0] = tmpValue[6];
238  NvOptions.cscMatrix[2][1] = tmpValue[7];
239  NvOptions.cscMatrix[2][2] = tmpValue[8];
240  }
241  }
242 
243  // Gamma correction vector values
244  if (deviceConfig->GetAttribute("GammaCorrection") != NULL)
245  {
246  float tmpValue[3];
247  if (deviceConfig->GetVectorAttribute("GammaCorrection", 3, tmpValue) == 3)
248  {
249  NvOptions.gamma[0] = tmpValue[0];
250  NvOptions.gamma[1] = tmpValue[1];
251  NvOptions.gamma[2] = tmpValue[2];
252  }
253  if (NvOptions.gamma[0] < 0.5 || NvOptions.gamma[0] > 6.0 ||
254  NvOptions.gamma[1] < 0.5 || NvOptions.gamma[1] > 6.0 ||
255  NvOptions.gamma[2] < 0.5 || NvOptions.gamma[2] > 6.0)
256  {
257  LOG_ERROR("Illegal gamma values specified.");
258  return PLUS_FAIL;
259  }
260  }
261 
262  // Flip queue length
263  int flipQueueLength;
264  if (deviceConfig->GetScalarAttribute("FlipQueueLength", flipQueueLength) != NULL)
265  {
266  NvOptions.flipQueueLength = flipQueueLength;
268  {
269  LOG_ERROR("Illegal number of flip queue buffers specified.");
270  return PLUS_FAIL;
271  }
272  }
273 
274  // GPU
275  int gpu;
276  if (deviceConfig->GetScalarAttribute("GPU", gpu) != NULL)
277  {
278  NvOptions.gpu = gpu;
279  if (NvOptions.gpu > 2)
280  {
281  LOG_ERROR("Illegal GPU specified.");
282  return PLUS_FAIL;
283  }
284  }
285 
286  // Video format
287  std::string videoFormat;
288  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(VideoFormat, videoFormat, deviceConfig);
289  if (videoFormat == "487i5994_259")
290  {
291  VideoSize[1] = 487;
292  NvOptions.videoFormat = NVVIOSIGNALFORMAT_487I_59_94_SMPTE259_NTSC;
293  }
294  else if (videoFormat == "576i5000_259")
295  {
296  VideoSize[1] = 576;
297  NvOptions.videoFormat = NVVIOSIGNALFORMAT_576I_50_00_SMPTE259_PAL;
298  }
299  else if (videoFormat == "720p2398_296")
300  {
301  VideoSize[1] = 720;
302  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_23_98_SMPTE296;
303  }
304  else if (videoFormat == "720p2400_296")
305  {
306  VideoSize[1] = 720;
307  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_24_00_SMPTE296;
308  }
309  else if (videoFormat == "720p2500_296")
310  {
311  VideoSize[1] = 720;
312  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_25_00_SMPTE296;
313  }
314  else if (videoFormat == "720p2997_296")
315  {
316  VideoSize[1] = 720;
317  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_29_97_SMPTE296;
318  }
319  else if (videoFormat == "720p3000_296")
320  {
321  VideoSize[1] = 720;
322  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_30_00_SMPTE296;
323  }
324  else if (videoFormat == "720p5000_296")
325  {
326  VideoSize[1] = 720;
327  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_50_00_SMPTE296;
328  }
329  else if (videoFormat == "720p5994_296")
330  {
331  VideoSize[1] = 720;
332  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_59_94_SMPTE296;
333  }
334  else if (videoFormat == "720p6000_296")
335  {
336  VideoSize[1] = 720;
337  NvOptions.videoFormat = NVVIOSIGNALFORMAT_720P_60_00_SMPTE296;
338  }
339  else if (videoFormat == "1035i5994_260")
340  {
341  VideoSize[1] = 1035;
342  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1035I_59_94_SMPTE260;
343  }
344  else if (videoFormat == "1035i6000_260")
345  {
346  VideoSize[1] = 1035;
347  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1035I_60_00_SMPTE260;
348  }
349  else if (videoFormat == "1080i4796_274")
350  {
351  VideoSize[1] = 1080;
352  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_47_96_SMPTE274;
353  }
354  else if (videoFormat == "1080i4800_274")
355  {
356  VideoSize[1] = 1080;
357  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_48_00_SMPTE274;
358  }
359  else if (videoFormat == "1080i5000_295")
360  {
361  VideoSize[1] = 1080;
362  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_50_00_SMPTE295;
363  }
364  else if (videoFormat == "1080i5000_274")
365  {
366  VideoSize[1] = 1080;
367  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_50_00_SMPTE274;
368  }
369  else if (videoFormat == "1080i5994_274")
370  {
371  VideoSize[1] = 1080;
372  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_59_94_SMPTE274;
373  }
374  else if (videoFormat == "1080i6000_274")
375  {
376  VideoSize[1] = 1080;
377  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080I_60_00_SMPTE274;
378  }
379  else if (videoFormat == "1080psf23976_274")
380  {
381  VideoSize[1] = 1080;
382  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_23_98_SMPTE274;
383  }
384  else if (videoFormat == "1080psf2398_274")
385  {
386  VideoSize[1] = 1080;
387  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_23_98_SMPTE274;
388  }
389  else if (videoFormat == "1080psf2400_274")
390  {
391  VideoSize[1] = 1080;
392  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_24_00_SMPTE274;
393  }
394  else if (videoFormat == "1080psf2500_274")
395  {
396  VideoSize[1] = 1080;
397  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_25_00_SMPTE274;
398  }
399  else if (videoFormat == "1080psf2997_274")
400  {
401  VideoSize[1] = 1080;
402  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_29_97_SMPTE274;
403  }
404  else if (videoFormat == "1080psf3000_274")
405  {
406  VideoSize[1] = 1080;
407  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080PSF_30_00_SMPTE274;
408  }
409  else if (videoFormat == "1080p23976_274")
410  {
411  VideoSize[1] = 1080;
412  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080P_23_976_SMPTE274;
413  }
414  else if (videoFormat == "1080p2400_274")
415  {
416  VideoSize[1] = 1080;
417  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080P_24_00_SMPTE274;
418  }
419  else if (videoFormat == "1080p2500_274")
420  {
421  VideoSize[1] = 1080;
422  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080P_25_00_SMPTE274;
423  }
424  else if (videoFormat == "1080p2997_274")
425  {
426  VideoSize[1] = 1080;
427  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080P_29_97_SMPTE274;
428  }
429  else if (videoFormat == "1080p3000_274")
430  {
431  VideoSize[1] = 1080;
432  NvOptions.videoFormat = NVVIOSIGNALFORMAT_1080P_30_00_SMPTE274;
433  }
434  else if (videoFormat == "2048i4796_372")
435  {
436  VideoSize[1] = 2048;
437  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048I_47_96_SMPTE372;
438  }
439  else if (videoFormat == "2048i4800_372")
440  {
441  VideoSize[1] = 2048;
442  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048I_48_00_SMPTE372;
443  }
444  else if (videoFormat == "2048i5000_372")
445  {
446  VideoSize[1] = 2048;
447  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048I_50_00_SMPTE372;
448  }
449  else if (videoFormat == "2048i5994_372")
450  {
451  VideoSize[1] = 2048;
452  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048I_59_94_SMPTE372;
453  }
454  else if (videoFormat == "2048i6000_372")
455  {
456  VideoSize[1] = 2048;
457  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048I_60_00_SMPTE372;
458  }
459  else if (videoFormat == "2048p2398_372")
460  {
461  VideoSize[1] = 2048;
462  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048P_23_98_SMPTE372;
463  }
464  else if (videoFormat == "2048p2400_372")
465  {
466  VideoSize[1] = 2048;
467  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048P_24_00_SMPTE372;
468  }
469  else if (videoFormat == "2048p2500_372")
470  {
471  VideoSize[1] = 2048;
472  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048P_25_00_SMPTE372;
473  }
474  else if (videoFormat == "2048p2997_372")
475  {
476  VideoSize[1] = 2048;
477  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048P_29_97_SMPTE372;
478  }
479  else if (videoFormat == "2048p3000_372")
480  {
481  VideoSize[1] = 2048;
482  NvOptions.videoFormat = NVVIOSIGNALFORMAT_2048P_30_00_SMPTE372;
483  }
484  else
485  {
486  LOG_WARNING("Invalid video format in configuration file.");
487  NvOptions.videoFormat = NVVIOSIGNALFORMAT_NONE;
488  }
489 
490  // Data format
491  std::string dataFormat;
492  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(DataFormat, dataFormat, deviceConfig);
493  if (dataFormat == "r8g8b8_to_ycrcb444")
494  {
495  NvOptions.dataFormat = NVVIODATAFORMAT_R8G8B8_TO_YCRCB444;
496  }
497  else if (dataFormat == "r8g8b8a8_to_ycrcba4444")
498  {
499  NvOptions.dataFormat = NVVIODATAFORMAT_R8G8B8A8_TO_YCRCBA4444;
500  }
501  else if (dataFormat == "r8g8b8_to_ycrcb422")
502  {
503  NvOptions.dataFormat = NVVIODATAFORMAT_R8G8B8_TO_YCRCB422;
504  }
505  else if (dataFormat == "r8g8b8a8_to_ycrcb4224")
506  {
507  NvOptions.dataFormat = NVVIODATAFORMAT_R8G8B8A8_TO_YCRCBA4224;
508  }
509  else if (dataFormat == "r8g8b8_to_rgb444")
510  {
511  NvOptions.dataFormat = NVVIODATAFORMAT_X8X8X8_444_PASSTHRU;
512  }
513  else if (dataFormat == "r8g8b8a8_to_rgb4444")
514  {
515  NvOptions.dataFormat = NVVIODATAFORMAT_X8X8X8_444_PASSTHRU;
516  }
517  else if (dataFormat == "y10cr10cb10_to_ycrcb444")
518  {
519  NvOptions.dataFormat = NVVIODATAFORMAT_X10X10X10_444_PASSTHRU;
520  }
521  else if (dataFormat == "y10cr8cb8_to_ycrcb444")
522  {
523  NvOptions.dataFormat = NVVIODATAFORMAT_X10X10X10_444_PASSTHRU;
524  }
525  else if (dataFormat == "y10cr8cb8a10_to_ycrcb4444")
526  {
527  NvOptions.dataFormat = NVVIODATAFORMAT_X10X8X8A10_4444_PASSTHRU;
528  }
529  else if (dataFormat == "dual_r8g8b8_to_dual_ycrcb422")
530  {
531  NvOptions.dataFormat = NVVIODATAFORMAT_DUAL_R8G8B8_TO_DUAL_YCRCB422;
532  }
533  else if (dataFormat == "dual_y8cr8cb8_to_dual_ycrcb422")
534  {
535  NvOptions.dataFormat = NVVIODATAFORMAT_DUAL_X8X8X8_TO_DUAL_422_PASSTHRU;
536  }
537  else if (dataFormat == "r10g10b10_to_ycrcb422")
538  {
539  NvOptions.dataFormat = NVVIODATAFORMAT_R10G10B10_TO_YCRCB422;
540  }
541  else if (dataFormat == "r10g10b10_to_ycrcb444")
542  {
543  NvOptions.dataFormat = NVVIODATAFORMAT_R10G10B10_TO_YCRCB422;
544  }
545  else if (dataFormat == "y12cr12cb12_to_ycrcb444")
546  {
547  NvOptions.dataFormat = NVVIODATAFORMAT_X12X12X12_444_PASSTHRU;
548  }
549  else if (dataFormat == "y12cr12cb12_to_ycrcb422")
550  {
551  NvOptions.dataFormat = NVVIODATAFORMAT_X12X12X12_422_PASSTHRU;
552  }
553  else if (dataFormat == "y10cr10cb10_to_ycrcb422")
554  {
555  NvOptions.dataFormat = NVVIODATAFORMAT_Y10CR10CB10_TO_YCRCB422;
556  }
557  else if (dataFormat == "y8cr8cb8_to_ycrcb422")
558  {
559  NvOptions.dataFormat = NVVIODATAFORMAT_Y8CR8CB8_TO_YCRCB422;
560  }
561  else if (dataFormat == "y10cr8cb8a10_to_ycrcba4224")
562  {
563  NvOptions.dataFormat = NVVIODATAFORMAT_Y10CR8CB8A10_TO_YCRCBA4224;
564  }
565  else if (dataFormat == "r10g10b10_to_rgb444")
566  {
567  NvOptions.dataFormat = NVVIODATAFORMAT_R10G10B10_TO_RGB444;
568  }
569  else if (dataFormat == "r12g12b12_to_rgb444")
570  {
571  NvOptions.dataFormat = NVVIODATAFORMAT_X12X12X12_444_PASSTHRU;
572  }
573  else
574  {
575  NvOptions.dataFormat = NVVIODATAFORMAT_R8G8B8A8_TO_YCRCBA4224;
576  }
577 
578  // Sync source
579  if (deviceConfig->GetAttribute("SyncSource") != NULL)
580  {
581  std::string syncSource(deviceConfig->GetAttribute("SyncSource"));
582  if (syncSource == "bi")
583  {
584  NvOptions.syncType = NVVIOCOMPSYNCTYPE_BILEVEL;
585  NvOptions.syncSource = NVVIOSYNCSOURCE_COMPSYNC;
587  }
588  else if (syncSource == "tri")
589  {
590  NvOptions.syncType = NVVIOCOMPSYNCTYPE_TRILEVEL;
591  NvOptions.syncSource = NVVIOSYNCSOURCE_COMPSYNC;
593  }
594  else if (syncSource == "auto")
595  {
596  NvOptions.syncType = NVVIOCOMPSYNCTYPE_AUTO;
597  NvOptions.syncSource = NVVIOSYNCSOURCE_COMPSYNC;
599  }
600  else if (syncSource == "sdi")
601  {
602  NvOptions.syncSource = NVVIOSYNCSOURCE_SDISYNC;
604  }
605  else
606  {
608  }
609  }
610 
611  // Alpha
612  if (deviceConfig->GetAttribute("Alpha") != NULL)
613  {
614  NvOptions.alphaComp = false;
615  if (STRCASECMP(deviceConfig->GetAttribute("Alpha"), "TRUE") == 0)
616  {
617  NvOptions.alphaComp = true;
618  }
619  }
620 
621  // Get compositing types and parameters
622  if (deviceConfig->GetAttribute("cr") != NULL)
623  {
624  NvOptions.crComp = true;
625  int tmpValue[4];
626  if (deviceConfig->GetVectorAttribute("cr", 4, tmpValue) == 4)
627  {
628  NvOptions.crCompRange[0] = tmpValue[0];
629  NvOptions.crCompRange[1] = tmpValue[1];
630  NvOptions.crCompRange[2] = tmpValue[2];
631  NvOptions.crCompRange[3] = tmpValue[3];
632  }
633  }
634 
635  if (deviceConfig->GetAttribute("cb") != NULL)
636  {
637  NvOptions.cbComp = true;
638  int tmpValue[4];
639  if (deviceConfig->GetVectorAttribute("cb", 4, tmpValue) == 4)
640  {
641  NvOptions.cbCompRange[0] = tmpValue[0];
642  NvOptions.cbCompRange[1] = tmpValue[1];
643  NvOptions.cbCompRange[2] = tmpValue[2];
644  NvOptions.cbCompRange[3] = tmpValue[3];
645  }
646  }
647 
648  if (deviceConfig->GetAttribute("y") != NULL)
649  {
650  NvOptions.yComp = true;
651  int tmpValue[4];
652  if (deviceConfig->GetVectorAttribute("y", 4, tmpValue) == 4)
653  {
654  NvOptions.yCompRange[0] = tmpValue[0];
655  NvOptions.yCompRange[1] = tmpValue[1];
656  NvOptions.yCompRange[2] = tmpValue[2];
657  NvOptions.yCompRange[3] = tmpValue[3];
658  }
659  }
660 
661  // Horizontal and vertical delay
662  int horizontalDelay;
663  if (deviceConfig->GetScalarAttribute("HorizontalDelay", horizontalDelay) != NULL)
664  {
665  NvOptions.hDelay = horizontalDelay;
666  }
667  int verticalDelay;
668  if (deviceConfig->GetScalarAttribute("VerticalDelay", verticalDelay) != NULL)
669  {
670  NvOptions.vDelay = verticalDelay;
671  }
672 
673  // Capture gpu
674  int captureGPU;
675  if (deviceConfig->GetScalarAttribute("CaptureGPU", captureGPU) != NULL)
676  {
677  NvOptions.captureGPU = captureGPU;
678  }
679 
680  // Capture device
681  int captureDevice;
682  if (deviceConfig->GetScalarAttribute("CaptureDevice", captureDevice) != NULL)
683  {
684  NvOptions.captureDevice = captureDevice;
685  }
686 
687  // Sampling
688  std::string sampling;
689  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(Sampling, sampling, deviceConfig);
690  if (sampling == "422")
691  {
692  NvOptions.sampling = NVVIOCOMPONENTSAMPLING_422;
693  }
694  else if (sampling == "444")
695  {
696  NvOptions.sampling = NVVIOCOMPONENTSAMPLING_444;
697  }
698  else if (sampling == "4224")
699  {
700  NvOptions.sampling = NVVIOCOMPONENTSAMPLING_4224;
701  }
702  else if (sampling == "4444")
703  {
704  NvOptions.sampling = NVVIOCOMPONENTSAMPLING_4444;
705  }
706 
707  // Bits per component
708  int bitsPerComponent;
709  if (deviceConfig->GetScalarAttribute("BitsPerComponent", bitsPerComponent) != NULL)
710  {
711  NvOptions.bitsPerComponent = bitsPerComponent;
712  }
713 
714  switch (NvOptions.sampling)
715  {
716  case NVVIOCOMPONENTSAMPLING_422:
717  if (NvOptions.bitsPerComponent == 8)
718  {
719  VideoBufferFormat = GL_YCBYCR8_422_NV;
720  }
721  else if (NvOptions.bitsPerComponent == 10)
722  {
723  VideoBufferFormat = GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV;
724  }
725  else //12 bit
726  {
727  NvOptions.dualLink = true;
728  VideoBufferFormat = GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV;
729  }
730  break;
731  case NVVIOCOMPONENTSAMPLING_4224:
732  NvOptions.dualLink = true;
733  if (NvOptions.bitsPerComponent == 8)
734  {
735  VideoBufferFormat = GL_YCBAYCR8A_4224_NV;
736  }
737  else if (NvOptions.bitsPerComponent == 10)
738  {
739  VideoBufferFormat = GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV;
740  }
741  else //12 bit
742  {
743  VideoBufferFormat = GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV;
744  }
745  break;
746  case NVVIOCOMPONENTSAMPLING_444:
747  NvOptions.dualLink = true;
748  if (NvOptions.bitsPerComponent == 8)
749  {
750  VideoBufferFormat = GL_RGB8;
751  }
752  else if (NvOptions.bitsPerComponent == 10)
753  {
754  VideoBufferFormat = GL_RGB10;
755  }
756  else //12 bit
757  {
758  VideoBufferFormat = GL_Z4Y12Z4CB12Z4CR12_444_NV;
759  }
760  VideoBufferFormat = GL_RGB8;
761  break;
762  case NVVIOCOMPONENTSAMPLING_4444:
763  NvOptions.dualLink = true;
764  if (NvOptions.bitsPerComponent == 8)
765  {
766  VideoBufferFormat = GL_RGBA8;
767  }
768  else if (NvOptions.bitsPerComponent == 10)
769  {
770  VideoBufferFormat = GL_RGBA12;
771  }
772  else //12 bit
773  {
774  VideoBufferFormat = GL_RGBA12;
775  }
776  break;
777  }
778 
779  if (NvOptions.captureDevice >= numCaptureDevices)
780  {
781  LOG_ERROR("Selected Capture Device is out of range.");
782  return PLUS_FAIL;
783  }
784  if (NvOptions.captureGPU >= numGPUs)
785  {
786  LOG_ERROR("Selected Capture GPU is out of range.");
787  return PLUS_FAIL;
788  }
789 
790  return PLUS_SUCCESS;
791 }
792 
793 //-----------------------------------------------------------------------------
794 PlusStatus vtkPlusNvidiaDVPVideoSource::WriteConfiguration(vtkXMLDataElement* rootConfig)
795 {
796  LOG_TRACE("vtkPlusNvidiaDVPVideoSource::WriteConfiguration");
797  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfig);
798 
799  XML_WRITE_BOOL_ATTRIBUTE(EnableGPUCPUCopy, deviceConfig);
800 
801  return PLUS_SUCCESS;
802 }
803 
804 //-----------------------------------------------------------------------------
806 {
807  if (this->OutputChannels.size() != 1 && this->EnableGPUCPUCopy)
808  {
809  LOG_ERROR("Incorrect configuration. GPU/CPU copy and OutputChannel configuration are incompatible.");
810  this->SetCorrectlyConfigured(false);
811  return PLUS_FAIL;
812  }
813 
815  {
816  LOG_ERROR("Unable to find video source. Device needs a video buffer to put new frames into when copying frames from the GPU.");
817  this->SetCorrectlyConfigured(false);
818  return PLUS_FAIL;
819  }
820 
821  return PLUS_SUCCESS;
822 }
823 
824 //----------------------------------------------------------------------------
826 {
827  return false;
828 }
829 
830 
831 //-----------------------------------------------------------------------------
833 {
834  if (SetupSDIinDevices() != S_OK)
835  {
836  LOG_ERROR("Error setting up video capture.");
837  return E_FAIL;
838  }
839 
840  return S_OK;
841 }
842 
843 //-----------------------------------------------------------------------------
845 {
846  // Start video capture
847  if (NvSDIin.StartCapture() != S_OK)
848  {
849  LOG_ERROR("Error starting video capture.");
850  return E_FAIL;
851  }
852  return S_OK;
853 }
854 
855 //-----------------------------------------------------------------------------
857 {
859  return S_OK;
860 }
861 
862 //-----------------------------------------------------------------------------
864 {
866 
867  // Initialize the video capture device.
869  {
870  return E_FAIL;
871  }
872 
873  VideoSize[0] = NvSDIin.GetWidth();
874  VideoSize[1] = NvSDIin.GetHeight();
875 
876  return S_OK;
877 }
878 
879 //-----------------------------------------------------------------------------
881 {
882  GLuint gpuVideoSlot = 1;
883 
884  NvSDIin.BindDevice(gpuVideoSlot, HandleDC);
885 
887 
888  int videoBufferPitch = 0;
889  for (unsigned int i = 0; i < NvSDIin.GetNumStreams(); i++)
890  {
892  videoBufferPitch = NvSDIin.GetBufferObjectPitch(i);
893 
894  // Allocate required space in video capture buffer
895  glBindBuffer(GL_VIDEO_BUFFER_NV, VideoBufferObject[i]);
896  assert(glGetError() == GL_NO_ERROR);
897 
898  glBufferData(GL_VIDEO_BUFFER_NV, videoBufferPitch * VideoHeight, NULL, GL_STREAM_COPY);
899  assert(glGetError() == GL_NO_ERROR);
900  }
901 
902  return S_OK;
903 }
904 
905 //-----------------------------------------------------------------------------
907 {
908  HGPUNV gpuMask[2];
909  gpuMask[0] = NvGPU->getAffinityHandle();
910  gpuMask[1] = NULL;
911  if (!(HandleDC = wglCreateAffinityDCNV(gpuMask)))
912  {
913  LOG_WARNING("Unable to create GPU affinity DC.");
914  }
915 
916  PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
917  {
918  sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
919  1, // Version Number
920  PFD_DRAW_TO_WINDOW | // Format Must Support Window
921  PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
922  PFD_DOUBLEBUFFER, // Must Support Double Buffering
923  PFD_TYPE_RGBA, // Request An RGBA Format
924  24, // Select Our Color Depth
925  0, 0, 0, 0, 0, 0, // Color Bits Ignored
926  1, // Alpha Buffer
927  0, // Shift Bit Ignored
928  0, // No Accumulation Buffer
929  0, 0, 0, 0, // Accumulation Bits Ignored
930  24, // 24 Bit Z-Buffer (Depth Buffer)
931  8, // 8 Bit Stencil Buffer
932  0, // No Auxiliary Buffer
933  PFD_MAIN_PLANE, // Main Drawing Layer
934  0, // Reserved
935  0, 0, 0 // Layer Masks Ignored
936  };
937  GLuint pf = ChoosePixelFormat(HandleDC, &pfd);
938  BOOL result = SetPixelFormat(HandleDC, pf, &pfd);
939  if (result == FALSE)
940  {
941  return GL_FALSE;
942  }
943  // Create rendering context from the affinity device context
944  HandleGLRC = wglCreateContext(HandleDC);
945 
946  // Make window rendering context current.
947  wglMakeCurrent(HandleDC, HandleGLRC);
948 
949  //load the required OpenGL extensions:
951  {
952  LOG_ERROR("Could not load the required OpenGL extensions.");
953  return false;
954  }
955 
956  glClearColor(0.0, 0.0, 0.0, 0.0);
957  glClearDepth(1.0);
958 
959  glDisable(GL_DEPTH_TEST);
960 
961  glDisable(GL_TEXTURE_1D);
962  glDisable(GL_TEXTURE_2D);
963 
964  SetupSDIinGL();
965  return GL_TRUE;
966 }
967 
968 //-----------------------------------------------------------------------------
970 {
971  static GLuint64EXT captureTime;
972  GLuint sequenceNum;
973  static GLuint prevSequenceNum = 0;
974  GLenum ret;
975  static int numFails = 0;
976  static int numTries = 0;
977 
978  if (numFails < 100)
979  {
980  // Capture the video to a buffer object
981  ret = NvSDIin.Capture(&sequenceNum, &captureTime);
982  if (sequenceNum - prevSequenceNum > 1)
983  {
984  LOG_WARNING("glVideoCaptureNV: Dropped " << sequenceNum - prevSequenceNum << " frames.");
985  }
986  prevSequenceNum = sequenceNum;
987  switch (ret)
988  {
989  case GL_SUCCESS_NV:
990  LOG_DEBUG("Frame: " << sequenceNum << ". gpuTime: " << NvSDIin.m_gpuTime << ". gviTime: " << NvSDIin.m_gviTime << ".");
991  numFails = 0;
992  break;
993  case GL_PARTIAL_SUCCESS_NV:
994  LOG_WARNING("glVideoCaptureNV: GL_PARTIAL_SUCCESS_NV.");
995  numFails = 0;
996  break;
997  case GL_FAILURE_NV:
998  LOG_ERROR("glVideoCaptureNV: GL_FAILURE_NV - Video capture failed.");
999  numFails++;
1000  break;
1001  default:
1002  LOG_ERROR("glVideoCaptureNV: Unknown return value.");
1003  break;
1004  }
1005  }
1006  // The incoming signal format or some other error occurred during
1007  // capture, shutdown and try to restart capture.
1008  else
1009  {
1010  if (numTries == 0)
1011  {
1012  StopSDIPipeline();
1014  CleanupGL();
1015  }
1016  // Initialize the video capture device.
1018  {
1019  numTries++;
1020  return GL_FAILURE_NV;
1021  }
1022 
1023  // Reinitialize OpenGL.
1024  SetupGL();
1025  StartSDIPipeline();
1026  numFails = 0;
1027  numTries = 0;
1028  return GL_FAILURE_NV;
1029  }
1030  return ret;
1031 }
1032 
1033 //-----------------------------------------------------------------------------
1035 {
1036  for (unsigned int i = 0; i < NvSDIin.GetNumStreams(); i++)
1037  {
1039  }
1042  return S_OK;
1043 }
1044 
1045 //-----------------------------------------------------------------------------
1047 {
1048  CleanupSDIinGL();
1049 
1050  // Delete OpenGL rendering context.
1051  wglMakeCurrent(NULL, NULL);
1052 
1053  return S_OK;
1054 }
1055 
1056 //-----------------------------------------------------------------------------
1058 {
1059  return S_OK;
1060 }
1061 
1062 //-----------------------------------------------------------------------------
1064 {
1065  StopSDIPipeline();
1066  CleanupGL();
1068 }
1069 
1070 //-----------------------------------------------------------------------------
1072 {
1073  glBindBuffer(GL_VIDEO_BUFFER_NV, VideoBufferObject[0]);
1074 
1075  // Transfer contents of video buffer(s) to system memory
1076  glGetBufferSubData(GL_VIDEO_BUFFER_NV, 0, NvSDIin.GetBufferObjectPitch(0) * VideoSize[1], CPUFrame);
1077 
1078  return S_OK;
1079 }
int hDelay
Definition: nvCommon.h:81
int gpu
Definition: nvCommon.h:76
vtkPlusDataSource * OutputDataSource
Data source for CPU output (if enabled)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
HRESULT StartCapture()
Definition: nvSDIin.cpp:975
bool EnableGPUCPUCopy
Enable copying of frame data from GPU to CPU for broadcasting.
virtual CNvGpu * GetGpu(int index)
Definition: nvGPUutil.cpp:271
int bitsPerComponent
Definition: nvCommon.h:112
double cscScale[3]
Definition: nvCommon.h:89
NVVIODATAFORMAT dataFormat
Definition: nvCommon.h:68
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
float gamma[3]
Definition: nvCommon.h:91
NVVIOSYNCSOURCE syncSource
Definition: nvCommon.h:70
bool block
Definition: nvCommon.h:77
int fsaa
Definition: nvCommon.h:80
GLenum Capture(GLuint *sequenceNum, GLuint64EXT *captureTime)
Definition: nvSDIin.cpp:1012
unsigned int GetHeight()
Definition: nvSDIin.cpp:263
igsioStatus PlusStatus
Definition: PlusCommon.h:40
HRESULT UnbindVideoFrameBuffer(unsigned int stream)
Definition: nvSDIin.cpp:969
bool field
Definition: nvCommon.h:84
float cscMatrix[3][3]
Definition: nvCommon.h:90
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)
float m_gviTime
Definition: nvSDIin.h:85
bool cbComp
Definition: nvCommon.h:95
static CNvSDIinTopology & Instance()
Definition: nvSDIin.cpp:73
for i
HRESULT BindDevice(GLuint videoSlot, HDC hDC)
Definition: nvSDIin.cpp:641
int GetNumDevice()
Definition: nvSDIin.cpp:80
#define PLUS_FAIL
Definition: PlusCommon.h:43
bool frameLock
Definition: nvCommon.h:73
bool videoInfo
Definition: nvCommon.h:78
CNvSDIin NvSDIin
Capture interface class.
HRESULT SetupDevice(int deviceNumber=0)
Definition: nvSDIin.cpp:554
bool log
Definition: nvCommon.h:86
PlusStatus GetFirstVideoSource(vtkPlusDataSource *&anImage)
PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData
bool loadBufferObjectExtension()
virtual PlusStatus Disconnect()
int cbCompRange[4]
Definition: nvCommon.h:98
#define FALSE
Definition: ATC3DGm.h:220
NVVIOCOMPONENTSAMPLING sampling
Definition: nvCommon.h:111
virtual PlusStatus NotifyConfigured()
Perform any completion tasks once configured.
nvOptions NvOptions
Options to configure capture.
virtual void SetCorrectlyConfigured(bool)
bool loadTimerQueryExtension()
PFNWGLCREATEAFFINITYDCNVPROC wglCreateAffinityDCNV
vtkStandardNewMacro(vtkPlusNvidiaDVPVideoSource)
bool yComp
Definition: nvCommon.h:93
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
HRESULT BindVideoFrameBuffer(GLuint videoBuffer, GLint videoBufferFormat, unsigned int stream)
Definition: nvSDIin.cpp:924
NVVIOCOMPSYNCTYPE syncType
Definition: nvCommon.h:69
HRESULT Init(nvOptions *options=NULL)
Definition: nvSDIin.cpp:294
bool console
Definition: nvCommon.h:85
bool alphaComp
Definition: nvCommon.h:92
unsigned char * CPUFrame
CPU memory storage of image.
float m_gpuTime
Definition: nvSDIin.h:86
PFNGLBUFFERDATAARBPROC glBufferData
bool crComp
Definition: nvCommon.h:94
uint64_t FrameNumber
The current frame number.
int repeat
Definition: nvCommon.h:75
HGPUNV getAffinityHandle()
Definition: nvGPUutil.cpp:340
bool fps
Definition: nvCommon.h:79
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
int flipQueueLength
Definition: nvCommon.h:83
NVVIOSIGNALFORMAT videoFormat
Definition: nvCommon.h:67
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers
bool dualLink
Definition: nvCommon.h:110
unsigned int GetWidth()
Definition: nvSDIin.cpp:257
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
bool syncEnable
Definition: nvCommon.h:72
virtual bool IsTracker() const
Respond to the query if this is a tracker or not.
int yCompRange[4]
Definition: nvCommon.h:96
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
Read configuration from XML data.
ChannelContainer OutputChannels
unsigned int GetNumStreams()
Definition: nvSDIin.cpp:957
#define TRUE
Definition: ATC3DGm.h:219
bool loadCaptureVideoExtension()
int GetBufferObjectPitch(unsigned int streamIndex)
Definition: nvSDIin.cpp:943
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
int numFrames
Definition: nvCommon.h:74
bool expansionEnable
Definition: nvCommon.h:113
int captureDevice
Definition: nvCommon.h:109
int GetPrimaryGpuIndex()
Definition: nvGPUutil.cpp:281
int BOOL
Definition: ATC3DGm.h:446
FrameSizeType GetInputFrameSize() const
int vDelay
Definition: nvCommon.h:82
HRESULT EndCapture()
Definition: nvSDIin.cpp:1043
PFNGLBINDBUFFERARBPROC glBindBuffer
PFNGLGENBUFFERSARBPROC glGenBuffers
static CNvGpuTopology & Instance()
Definition: nvGPUutil.cpp:258
int captureGPU
Definition: nvCommon.h:108
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
Write configuration to XML data.
HRESULT UnbindDevice()
Definition: nvSDIin.cpp:1056
Class for providing VTK video input interface from an NVidia digital video platform interface.
double cscOffset[3]
Definition: nvCommon.h:88
int crCompRange[4]
Definition: nvCommon.h:97