1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkMILVideoSource.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkMILVideoSource.h"
16 #include "vtkTimerLog.h"
17 #include "vtkObjectFactory.h"
18 #include "vtkCriticalSection.h"
19 
20 #include <mil.h>
21 #include <cctype>
22 #include <cstring>
23 
24 vtkStandardNewMacro(vtkMILVideoSource);
25 
26 //----------------------------------------------------------------------------
vtkMILVideoSource()27 vtkMILVideoSource::vtkMILVideoSource()
28 {
29   this->Initialized = 0;
30 
31   this->FatalMILError = 0;
32 
33   this->ContrastLevel = 1.0;
34   this->BrightnessLevel = 128;
35   this->HueLevel = 0.0;
36   this->SaturationLevel = 1.0;
37   this->BlackLevel = 0.0;
38   this->WhiteLevel = 255.0;
39 
40   this->VideoChannel = 0;
41   this->VideoInput = VTK_MIL_MONO;
42   this->VideoInputForColor = VTK_MIL_YC;
43   this->VideoFormat = VTK_MIL_RS170;
44 
45   this->FrameMaxSize[0] = 640;
46   this->FrameMaxSize[1] = 480;
47 
48   this->OldHookFunction = 0;
49   this->OldUserDataPtr = 0;
50 
51   this->MILAppID = 0;
52   this->MILSysID = 0;
53   this->MILDigID = 0;
54   this->MILBufID = 0;
55   //this->MILDispBufID = 0;
56   //this->MILDispID = 0;
57 
58   this->MILAppInternallyAllocated = 0;
59   this->MILSysInternallyAllocated = 0;
60 
61   this->MILSystemType = VTK_MIL_DEFAULT;
62   this->MILSystemNumber = M_DEFAULT;
63 
64   this->MILDigitizerNumber = M_DEFAULT;
65   this->MILDigitizerDCF = nullptr;
66 
67   this->MILErrorMessages = 1;
68 
69   this->FlipFrames = 1; //apply vertical flip to each frame
70 
71   // for accurate timing
72   this->LastTimeStamp = 0;
73   this->LastFrameCount = 0;
74   this->EstimatedFramePeriod = 0.033;
75   this->NextFramePeriod = 0.033;
76 }
77 
78 //----------------------------------------------------------------------------
~vtkMILVideoSource()79 vtkMILVideoSource::~vtkMILVideoSource()
80 {
81   this->vtkMILVideoSource::ReleaseSystemResources();
82 
83   delete [] this->MILDigitizerDCF;
84   this->MILDigitizerDCF = nullptr;
85 
86   this->SetMILSystemType(0);
87 }
88 
89 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)90 void vtkMILVideoSource::PrintSelf(ostream& os, vtkIndent indent)
91 {
92   this->Superclass::PrintSelf(os,indent);
93 
94   os << indent << "VideoChannel: " << this->VideoChannel << "\n";
95 
96   os << indent << "ContrastLevel: " << this->ContrastLevel << "\n";
97 
98   os << indent << "BrightnessLevel: " << this->BrightnessLevel << "\n";
99 
100   os << indent << "HueLevel: " << this->HueLevel << "\n";
101 
102   os << indent << "SaturationLevel: " << this->SaturationLevel << "\n";
103 
104   os << indent << "BlackLevel: " << this->BlackLevel << "\n";
105 
106   os << indent << "WhiteLevel: " << this->WhiteLevel << "\n";
107 
108   os << indent << "VideoInput: ";
109   switch (this->VideoInput)
110   {
111     case VTK_MIL_MONO:
112       os << "Mono\n";
113       break;
114     case VTK_MIL_COMPOSITE:
115       os << "Mono\n";
116       break;
117     case VTK_MIL_YC:
118       os << "Mono\n";
119       break;
120     case VTK_MIL_RGB:
121       os << "Mono\n";
122       break;
123     case VTK_MIL_DIGITAL:
124       os << "Mono\n";
125       break;
126     default:
127       os << "Unrecognized\n";
128       break;
129   }
130 
131   os << indent << "VideoFormat: ";
132   switch (this->VideoFormat)
133   {
134     case VTK_MIL_RS170:
135       os << "RS170\n";
136       break;
137     case VTK_MIL_NTSC:
138       os << "NTSC\n";
139       break;
140     case VTK_MIL_CCIR:
141       os << "CCIR\n";
142       break;
143     case VTK_MIL_PAL:
144       os << "PAL\n";
145       break;
146     case VTK_MIL_SECAM:
147       os << "SECAM\n";
148       break;
149     default:
150       os << "Unrecognized\n";
151       break;
152   }
153 
154   os << indent << "MILSystemType: " <<
155     (this->MILSystemType ? this->MILSystemType : "Default") << "\n";
156 
157   os << indent << "MILSystemNumber: " << this->MILSystemNumber << "\n";
158 
159   os << indent << "MILDigitizerDCF: " << (this->MILDigitizerDCF ?
160     this->MILDigitizerDCF : "nullptr") << "\n";
161 
162   os << indent << "MILDigitizerNumber: " << this->MILDigitizerNumber << "\n";
163 
164   os << indent << "MILErrorMessages: " << (this->MILErrorMessages ? "On\n" : "Off\n");
165 
166   os << indent << "MILAppID: " << this->MILAppID << "\n";
167   os << indent << "MILSysID: " << this->MILSysID << "\n";
168   os << indent << "MILDigID: " << this->MILDigID << "\n";
169   os << indent << "MILBufID: " << this->MILBufID << "\n";
170   //  os << indent << "MILDispBufID: " << this->MILDispBufID << "\n";
171   //  os << indent << "MILDispID: " << this->MILDispID << "\n";
172 }
173 
174 //----------------------------------------------------------------------------
175 // load the DLL for the specified Matrox digitizer, for MIL 5 and MIL 6
MILInterpreterForSystem(const char * system)176 char *vtkMILVideoSource::MILInterpreterForSystem(const char *system)
177 {
178   char *dll_name;
179   char *func_name;
180 
181   if (strcmp(system,VTK_MIL_CORONA) == 0)
182   {
183     dll_name = "milcor";
184     func_name = "MDCoronaCommandDecoder";
185   }
186   else if (strcmp(system,VTK_MIL_METEOR) == 0)
187   {
188     dll_name = "milmet";
189     func_name = "MDMeteorCommandDecoder";
190   }
191   else if (strcmp(system,VTK_MIL_METEOR_II) == 0)
192   {
193     dll_name = "milmet2";
194     func_name = "MDMeteorIICommandDecoder";
195   }
196   else if (strcmp(system,VTK_MIL_METEOR_II_DIG) == 0)
197   {
198     dll_name = "milmet2d";
199     func_name = "MDMeteorIIDigCommandDecoder";
200   }
201   else if (strcmp(system,VTK_MIL_PULSAR) == 0)
202   {
203     dll_name = "milpul";
204     func_name = "MDPulsarCommandDecoder";
205   }
206   else if (strcmp(system,VTK_MIL_GENESIS) == 0)
207   {
208     dll_name = "milgen";
209     func_name = "MDGenesisCommandDecoder";
210   }
211   else if (strcmp(system,VTK_MIL_ORION) == 0)
212   {
213     dll_name = "milorion";
214     func_name = "MDOrionCommandDecoder";
215   }
216   else
217   {
218     dll_name = "unknown";
219     func_name = "unknown";
220   }
221 
222   // first try mil.dll (for later versions of mil)
223   this->MILInterpreterDLL = "mil";
224   HINSTANCE mil_lib = LoadLibrary("mil");
225   if (mil_lib == 0)
226   {
227     return nullptr;
228   }
229   void *proc_address = (void *)GetProcAddress(mil_lib,func_name);
230   if (proc_address)
231   {
232     return proc_address;
233   }
234 
235   // then try the device-specific dll
236   this->MILInterpreterDLL = dll_name;
237   mil_lib = LoadLibrary(dll_name);
238 
239   if (mil_lib == 0)
240   {
241     return nullptr;
242   }
243 
244   return (char *)GetProcAddress(mil_lib,func_name);
245 }
246 
247 //----------------------------------------------------------------------------
vtkMILVideoSourceSetChannel(long digID,int channel)248 static void vtkMILVideoSourceSetChannel(long digID, int channel)
249 {
250   if (digID == 0)
251   {
252     return;
253   }
254 
255   int mil_channel = M_DEFAULT;
256 
257   switch(channel)
258   {
259     case 0:
260       mil_channel = M_CH0;
261       break;
262     case 1:
263       mil_channel = M_CH1;
264       break;
265     case 2:
266       mil_channel = M_CH2;
267       break;
268     case 3:
269       mil_channel = M_CH3;
270       break;
271   }
272 
273   MdigChannel(digID,mil_channel);
274 }
275 
276 //----------------------------------------------------------------------------
vtkMILVideoSourceSetLevel(long digID,int ref,float level)277 static void vtkMILVideoSourceSetLevel(long digID, int ref, float level)
278 {
279   if (digID == 0)
280   {
281     return;
282   }
283 
284   long int_level = M_MIN_LEVEL + level*(M_MAX_LEVEL-M_MIN_LEVEL);
285 
286   if (int_level < M_MIN_LEVEL)
287   {
288     int_level = M_MIN_LEVEL;
289   }
290 
291   if (int_level > M_MAX_LEVEL)
292   {
293     int_level = M_MAX_LEVEL;
294   }
295 
296   MdigReference(digID,ref,int_level);
297 }
298 
299 //----------------------------------------------------------------------------
vtkMILVideoSourceSetSize(long digID,int size[3],int maxSize[2])300 static void vtkMILVideoSourceSetSize(long digID, int size[3], int maxSize[2])
301 {
302   if (digID == 0)
303   {
304     return;
305   }
306 
307   int shrink_x = maxSize[0]/size[0];
308   int shrink_y = maxSize[1]/size[1];
309   if (shrink_x < 1)
310   {
311     shrink_x = 1;
312   }
313   if (shrink_y < 1)
314   {
315     shrink_y = 1;
316   }
317 
318   // convert shrink_x, shrink_y to power of 2
319   int i;
320   for (i = 0; shrink_x; i++)
321   {
322     shrink_x = shrink_x >> 1;
323   }
324   shrink_x = 1 << (i-1);
325   for (i = 0; shrink_y; i++)
326   {
327     shrink_y = shrink_y >> 1;
328   }
329   shrink_y = 1 << (i-1);
330 
331   MdigControl(digID,M_GRAB_SCALE_X,1.0/shrink_x);
332   MdigControl(digID,M_GRAB_SCALE_Y,1.0/shrink_y);
333 }
334 
335 //----------------------------------------------------------------------------
Initialize()336 void vtkMILVideoSource::Initialize()
337 {
338   static char *system_types[] = { VTK_MIL_METEOR, VTK_MIL_METEOR_II,
339                                   VTK_MIL_METEOR_II_DIG, VTK_MIL_METEOR_II_CL,
340                                   VTK_MIL_METEOR_II_1394, VTK_MIL_CORONA_II,
341                                   VTK_MIL_CORONA, VTK_MIL_PULSAR,
342                                   VTK_MIL_GENESIS, VTK_MIL_GENESIS_PLUS,
343                                   VTK_MIL_ORION, VTK_MIL_CRONOS,
344                                   VTK_MIL_ODYSSEY, 0 };
345 
346   if (this->Initialized || this->FatalMILError)
347   {
348     return;
349   }
350 
351   this->Initialized = 1;
352 
353   // update the frame buffer now just in case there is an error
354   this->UpdateFrameBuffer();
355 
356   if (this->MILAppID == 0)
357   {
358     this->MILAppID = MappAlloc(M_DEFAULT,M_NULL);
359     if (this->MILAppID == 0)
360     {
361       this->ReleaseSystemResources();
362       vtkErrorMacro(<< "Initialize: couldn't open MIL application\n");
363       return;
364     }
365     this->MILAppInternallyAllocated = 1;
366   }
367 
368   long version = MappInquire(M_VERSION,M_NULL);
369 
370   if (this->MILSysID == 0)
371   {
372     char *systemType;
373     if (this->MILSystemType != VTK_MIL_DEFAULT)
374     { // asked for a particular system by name
375       if (version >= 7)
376       {  // try MIL 7 style of allocation
377         char tmptext[256];
378         strncpy(tmptext,"\\\\.\\",4);
379         strncpy(&tmptext[4],this->MILSystemType,252);
380         this->MILSysID = MsysAlloc(tmptext,this->MILSystemNumber,
381                                    M_DEFAULT,M_NULL);
382       }
383       else
384       { // try MIL 5, MIL 6 which requires loading the appropriate DLL
385         systemType = this->MILInterpreterForSystem(this->MILSystemType);
386         if (systemType)
387         {
388           this->MILSysID = MsysAlloc(systemType, this->MILSystemNumber,
389                                      M_DEFAULT,M_NULL);
390         }
391       }
392 
393       if (this->MILSysID == 0)
394       {
395         this->ReleaseSystemResources();
396         vtkErrorMacro(<< "Initialize: couldn't find " << this->MILInterpreterDLL << ".dll\n");
397         return;
398       }
399     }
400     else
401     { // try for any known MIL system
402       MappControl(M_ERROR,M_PRINT_DISABLE);
403       int i;
404       for (i = 0; this->MILSysID == 0 && system_types[i] != 0; i++)
405       {
406         if (version >= 7)
407         {
408           // try MIL 7 style of allocation
409           char tmptext[256];
410           snprintf(tmptext,sizeof(tmptext),"\\\\.\\%s",system_types[i]);
411           this->MILSysID = MsysAlloc(tmptext,this->MILSystemNumber,
412                                      M_DEFAULT,M_NULL);
413         }
414         else
415         { // try MIL 5, MIL 6 which requires loading the appropriate DLL
416           systemType = this->MILInterpreterForSystem(system_types[i]);
417           if (systemType)
418           {
419             this->MILSysID = MsysAlloc(systemType,this->MILSystemNumber,
420                                      M_DEFAULT,M_NULL);
421           }
422         }
423       }
424       if (system_types[i] == 0)
425       {
426         this->ReleaseSystemResources();
427         vtkErrorMacro(<< "Initialize: Couldn't find a Matrox frame grabber on the system\n");
428         return;
429       }
430       MappControl(M_ERROR,M_PRINT_ENABLE);
431     }
432     this->MILSysInternallyAllocated = 1;
433   }
434 
435   this->AllocateMILBuffer();
436 
437   this->AllocateMILDigitizer();
438 
439   MappControl(M_ERROR,
440               ( this->MILErrorMessages ? M_PRINT_ENABLE : M_PRINT_DISABLE ));
441 
442   // update frame buffer again to reflect any changes
443   this->UpdateFrameBuffer();
444 }
445 
446 //----------------------------------------------------------------------------
ReleaseSystemResources()447 void vtkMILVideoSource::ReleaseSystemResources()
448 {
449   if (this->MILAppID != 0)
450   {
451     MappControl(M_ERROR, M_PRINT_DISABLE);
452   }
453   if (this->MILDigID)
454   {
455     if (this->Recording)
456     {
457       MdigHalt(this->MILDigID);
458     }
459     MdigGrabWait(this->MILDigID,M_GRAB_END);
460     this->Recording = 0;
461   }
462   /*
463   if (this->MILDispID != 0)
464     {
465     MdispDeselect(this->MILDispID,this->MILDispBufID);
466     MdispFree(this->MILDispID);
467     this->MILDispID = 0;
468     }
469   if (this->MILDispBufID != 0)
470     {
471     MbufFree(this->MILDispBufID);
472     this->MILDispBufID = 0;
473     }
474   */
475   if (this->MILBufID != 0)
476   {
477     MbufFree(this->MILBufID);
478     this->MILBufID = 0;
479   }
480   if (this->MILDigID != 0)
481   {
482     //  The MdigFree call never returns if it is called by atexit(),
483     //  and it doesn't seem to hurt anything if it isn't called.
484     MdigFree(this->MILDigID);
485     this->MILDigID = 0;
486   }
487   if (this->MILSysInternallyAllocated && this->MILSysID != 0)
488   {
489     MsysFree(this->MILSysID);
490     this->MILSysID = 0;
491   }
492   if (this->MILAppInternallyAllocated && this->MILAppID != 0)
493   {
494     MappFree(this->MILAppID);
495     this->MILAppID = 0;
496   }
497   this->Initialized = 0;
498   this->FatalMILError = 0;
499 }
500 
501 //----------------------------------------------------------------------------
vtkMILVideoSourceHook(long HookType,MIL_ID EventID,void * UserPtr)502 long MFTYPE vtkMILVideoSourceHook(long HookType, MIL_ID EventID, void *UserPtr)
503 {
504   vtkMILVideoSource *self = (vtkMILVideoSource *)UserPtr;
505 
506   if (HookType == M_GRAB_FRAME_END)
507   {
508     double time = 1000;
509     float rate = self->GetFrameRate();
510     int format = self->GetVideoFormat();
511     int frame_stride;
512     if (rate > 0)
513     {
514       frame_stride = (int)(30/rate);
515       if (format == VTK_MIL_CCIR ||
516           format == VTK_MIL_PAL ||
517           format == VTK_MIL_SECAM)
518       {
519         frame_stride = (int)(25/rate);
520       }
521     }
522     if ((rate > 0 && ++(self->FrameCounter) >= frame_stride) ||
523         self->ForceGrab)
524     {
525       self->InternalGrab();
526       self->FrameCounter = 0;
527       self->ForceGrab = 0;
528     }
529   }
530   if (self->OldHookFunction)
531   {
532     return ((MDIGHOOKFCTPTR)self->OldHookFunction)(HookType,EventID,
533                                              self->OldUserDataPtr);
534   }
535   else
536   {
537     return M_NULL;
538   }
539 }
540 
541 //----------------------------------------------------------------------------
InternalGrab()542 void vtkMILVideoSource::InternalGrab()
543 {
544   this->FrameBufferMutex->Lock();
545 
546   if (this->AutoAdvance)
547   {
548     this->AdvanceFrameBuffer(1);
549     if (this->FrameIndex + 1 < this->FrameBufferSize)
550     {
551       this->FrameIndex++;
552     }
553   }
554 
555   int index = this->FrameBufferIndex;
556 
557   this->FrameBufferTimeStamps[index] =
558     this->CreateTimeStampForFrame(this->LastFrameCount + 1);
559   if (this->FrameCount++ == 0)
560   {
561     this->StartTimeStamp = this->FrameBufferTimeStamps[index];
562   }
563 
564   void *ptr = ((reinterpret_cast<vtkDataArray *>( \
565                        this->FrameBuffer[index]))->GetVoidPointer(0));
566   int depth = this->FrameBufferBitsPerPixel/8;
567 
568   int offsetX = this->FrameBufferExtent[0];
569   int offsetY = this->FrameBufferExtent[2];
570 
571   int sizeX = this->FrameBufferExtent[1] - this->FrameBufferExtent[0] + 1;
572   int sizeY = this->FrameBufferExtent[3] - this->FrameBufferExtent[2] + 1;
573 
574   if (sizeX > 0 && sizeY > 0)
575   {
576     if (depth == 1)
577     {
578       MbufGet2d(this->MILBufID,offsetX,offsetY,sizeX,sizeY,ptr);
579     }
580     else if (depth == 3)
581     {
582       MbufGetColor2d(this->MILBufID,M_RGB24+M_PACKED,M_ALL_BAND,
583                      offsetX,offsetY,sizeX,sizeY,ptr);
584     }
585     else if (depth == 4)
586     {
587       MbufGetColor2d(this->MILBufID,M_RGB32+M_PACKED,M_ALL_BAND,
588                      offsetX,offsetY,sizeX,sizeY,ptr);
589     }
590   }
591 
592   this->Modified();
593 
594   this->FrameBufferMutex->Unlock();
595 }
596 
597 //----------------------------------------------------------------------------
598 // for accurate timing of the transformation: this solves a differential
599 // equation that works to smooth out the jitter in the times that
600 // are returned by vtkTimerLog::GetUniversalTime() i.e. the system clock.
CreateTimeStampForFrame(unsigned long framecount)601 double vtkMILVideoSource::CreateTimeStampForFrame(unsigned long framecount)
602 {
603   double timestamp = vtkTimerLog::GetUniversalTime();
604 
605   double frameperiod = ((timestamp - this->LastTimeStamp)/
606                         (framecount - this->LastFrameCount));
607   double deltaperiod = (frameperiod - this->EstimatedFramePeriod)*0.01;
608 
609   this->EstimatedFramePeriod += deltaperiod;
610   this->LastTimeStamp += ((framecount - this->LastFrameCount)*
611                           this->NextFramePeriod);
612   this->LastFrameCount = framecount;
613 
614   double diffperiod = (timestamp - this->LastTimeStamp);
615 
616   if (diffperiod < -0.2 || diffperiod > 0.2)
617   { // time is off by more than 0.2 seconds: reset the clock
618     this->EstimatedFramePeriod -= deltaperiod;
619     this->NextFramePeriod = this->EstimatedFramePeriod;
620     this->LastTimeStamp = timestamp;
621     return timestamp;
622   }
623 
624   diffperiod *= 0.1;
625   double maxdiff = 0.001;
626   if (diffperiod < -maxdiff)
627   {
628     diffperiod = -maxdiff;
629   }
630   else if (diffperiod > maxdiff)
631   {
632     diffperiod = maxdiff;
633   }
634 
635   this->NextFramePeriod = this->EstimatedFramePeriod + diffperiod;
636 
637   return this->LastTimeStamp;
638 }
639 
640 //----------------------------------------------------------------------------
641 // Circulate the buffer and grab a frame.
642 // This particular implementation just copies random noise into the frames,
643 // you will certainly want to override this method (also note that this
644 // is the only method which you really have to override)
Grab()645 void vtkMILVideoSource::Grab()
646 {
647   // ensure that the hardware is initialized.
648   this->Initialize();
649   if (!this->Initialized)
650   {
651     return;
652   }
653 
654   if (!this->Recording)
655   {
656     MdigGrab(this->MILDigID,this->MILBufID);
657     MdigGrabWait(this->MILDigID,M_GRAB_END);
658     this->InternalGrab();
659   }
660   else
661   {
662     this->ForceGrab = 1;
663   }
664 }
665 
666 //----------------------------------------------------------------------------
Play()667 void vtkMILVideoSource::Play()
668 {
669   vtkVideoSource::Play();
670 }
671 
672 //----------------------------------------------------------------------------
Record()673 void vtkMILVideoSource::Record()
674 {
675   this->Initialize();
676   if (!this->Initialized)
677   {
678     return;
679   }
680 
681   if (this->Playing)
682   {
683     this->Stop();
684   }
685 
686   if (this->Recording)
687   {
688     return;
689   }
690 
691   this->Recording = 1;
692   this->FrameCount = 0;
693 
694   MdigInquire(this->MILDigID,M_GRAB_FRAME_END_HANDLER_PTR,
695               &this->OldHookFunction);
696   MdigInquire(this->MILDigID,M_GRAB_FRAME_END_HANDLER_USER_PTR,
697               &this->OldUserDataPtr);
698   MdigHookFunction(this->MILDigID,M_GRAB_FRAME_END,
699                    &vtkMILVideoSourceHook,
700                    (void *)this);
701   this->FrameCounter = 0;
702   this->ForceGrab = 0;
703 
704   // for accurate timing
705   this->LastTimeStamp = vtkTimerLog::GetUniversalTime();
706 
707   // this will call the hook function on every frame
708   MdigGrabContinuous(this->MILDigID,this->MILBufID);
709 
710   this->Modified();
711 }
712 
713 //----------------------------------------------------------------------------
Stop()714 void vtkMILVideoSource::Stop()
715 {
716   if (this->Playing)
717   {
718     vtkVideoSource::Stop();
719   }
720 
721   if (!this->Recording)
722   {
723     return;
724   }
725 
726   this->Recording = 0;
727 
728   MdigHalt(this->MILDigID);
729   MdigHookFunction(this->MILDigID,M_GRAB_FRAME_END,
730                    (MDIGHOOKFCTPTR)this->OldHookFunction,
731                    this->OldUserDataPtr);
732   this->OldHookFunction = 0;
733   MdigGrabWait(this->MILDigID,M_GRAB_END);
734 
735   this->Modified();
736 }
737 
738 //----------------------------------------------------------------------------
SetMILErrorMessages(int yesno)739 void vtkMILVideoSource::SetMILErrorMessages(int yesno)
740 {
741   if (this->MILErrorMessages == yesno)
742   {
743     return;
744   }
745 
746   this->MILErrorMessages = yesno;
747   this->Modified();
748 
749   if (this->Initialized)
750   {
751     MappControl(M_ERROR,( yesno ? M_PRINT_ENABLE : M_PRINT_DISABLE ));
752   }
753 }
754 
755 //----------------------------------------------------------------------------
SetFrameSize(int x,int y,int z)756 void vtkMILVideoSource::SetFrameSize(int x, int y, int z)
757 {
758   if (x == this->FrameSize[0] &&
759       y == this->FrameSize[1] &&
760       z == this->FrameSize[2])
761   {
762     return;
763   }
764 
765   if (x < 1 || y < 1 || z != 1)
766   {
767     vtkErrorMacro(<< "SetFrameSize: Illegal frame size");
768     return;
769   }
770 
771   this->FrameSize[0] = x;
772   this->FrameSize[1] = y;
773   this->FrameSize[2] = z;
774 
775   if (this->Initialized)
776   {
777     this->FrameBufferMutex->Lock();
778     this->UpdateFrameBuffer();
779     vtkMILVideoSourceSetSize(this->MILDigID,
780                              this->FrameSize,this->FrameMaxSize);
781     this->AllocateMILBuffer();
782     this->FrameBufferMutex->Unlock();
783   }
784 
785   this->Modified();
786 }
787 
788 //----------------------------------------------------------------------------
SetOutputFormat(int format)789 void vtkMILVideoSource::SetOutputFormat(int format)
790 {
791   if (format == this->OutputFormat)
792   {
793     return;
794   }
795 
796   this->OutputFormat = format;
797 
798   // convert color format to number of scalar components
799   int numComponents;
800 
801   switch (this->OutputFormat)
802   {
803     case VTK_RGBA:
804       numComponents = 4;
805       break;
806     case VTK_RGB:
807       numComponents = 3;
808       break;
809     case VTK_LUMINANCE:
810       numComponents = 1;
811       break;
812     default:
813       vtkErrorMacro(<< "SetOutputFormat: Unrecognized color format.");
814       break;
815   }
816   this->NumberOfScalarComponents = numComponents;
817 
818   if (this->FrameBufferBitsPerPixel != numComponents*8)
819   {
820     this->FrameBufferMutex->Lock();
821     this->FrameBufferBitsPerPixel = numComponents*8;
822     if (this->Initialized)
823     {
824       this->UpdateFrameBuffer();
825       this->AllocateMILBuffer();
826     }
827     this->FrameBufferMutex->Unlock();
828   }
829 
830   // set video format to match the output format
831   if (this->OutputFormat == VTK_RGB || this->OutputFormat == VTK_RGBA)
832   {
833     if (this->VideoFormat == VTK_MIL_RS170)
834     {
835       this->SetVideoFormat(VTK_MIL_NTSC);
836     }
837     if (this->VideoFormat == VTK_MIL_CCIR)
838     {
839       this->SetVideoFormat(VTK_MIL_PAL);
840     }
841     if (this->VideoInput == VTK_MIL_MONO)
842     {
843       this->SetVideoInput(this->VideoInputForColor);
844     }
845   }
846   if (this->OutputFormat == VTK_LUMINANCE)
847   {
848     if (this->VideoFormat == VTK_MIL_NTSC)
849     {
850       this->SetVideoFormat(VTK_MIL_RS170);
851     }
852     if (this->VideoFormat == VTK_MIL_PAL)
853     {
854       this->SetVideoFormat(VTK_MIL_CCIR);
855     }
856     if (this->VideoInput == VTK_MIL_YC || this->VideoInput == VTK_MIL_COMPOSITE)
857     {
858       this->VideoInputForColor = this->VideoInput;
859       this->SetVideoInput(VTK_MIL_MONO);
860     }
861   }
862 
863   this->Modified();
864 }
865 
866 //----------------------------------------------------------------------------
SetVideoFormat(int format)867 void vtkMILVideoSource::SetVideoFormat(int format)
868 {
869   if (this->VideoFormat == format)
870   {
871     return;
872   }
873 
874   this->VideoFormat = format;
875 
876   // don't do anything if the digitizer isn't initialized
877   if (this->Initialized)
878   {
879     this->AllocateMILDigitizer();
880   }
881 }
882 
883 //----------------------------------------------------------------------------
SetVideoInput(int input)884 void vtkMILVideoSource::SetVideoInput(int input)
885 {
886   if (this->VideoInput == input)
887   {
888     return;
889   }
890 
891   this->VideoInput = input;
892 
893   // don't do anything if the digitizer isn't initialized
894   if (this->Initialized)
895   {
896     this->AllocateMILDigitizer();
897   }
898 }
899 
900 //----------------------------------------------------------------------------
SetVideoChannel(int channel)901 void vtkMILVideoSource::SetVideoChannel(int channel)
902 {
903   if (this->VideoChannel == channel)
904   {
905     return;
906   }
907 
908   this->VideoChannel = channel;
909   this->Modified();
910 
911   vtkMILVideoSourceSetChannel(this->MILDigID,channel);
912 }
913 
914 //----------------------------------------------------------------------------
SetBrightnessLevel(float brightness)915 void vtkMILVideoSource::SetBrightnessLevel(float brightness)
916 {
917   if (this->BrightnessLevel == brightness)
918   {
919     return;
920   }
921 
922   this->BrightnessLevel = brightness;
923   this->Modified();
924 
925   vtkMILVideoSourceSetLevel(this->MILDigID,M_BRIGHTNESS_REF,brightness/255.0);
926 }
927 
928 //----------------------------------------------------------------------------
SetContrastLevel(float contrast)929 void vtkMILVideoSource::SetContrastLevel(float contrast)
930 {
931   if (this->ContrastLevel == contrast)
932   {
933     return;
934   }
935 
936   this->ContrastLevel = contrast;
937   this->Modified();
938 
939   vtkMILVideoSourceSetLevel(this->MILDigID,M_CONTRAST_REF,contrast/2.0);
940 }
941 
942 //----------------------------------------------------------------------------
SetHueLevel(float hue)943 void vtkMILVideoSource::SetHueLevel(float hue)
944 {
945   if (this->HueLevel == hue)
946   {
947     return;
948   }
949 
950   this->HueLevel = hue;
951   this->Modified();
952 
953   vtkMILVideoSourceSetLevel(this->MILDigID,M_HUE_REF,0.5+hue);
954 }
955 
956 //----------------------------------------------------------------------------
SetSaturationLevel(float saturation)957 void vtkMILVideoSource::SetSaturationLevel(float saturation)
958 {
959   if (this->SaturationLevel == saturation)
960   {
961     return;
962   }
963 
964   this->SaturationLevel = saturation;
965   this->Modified();
966 
967   vtkMILVideoSourceSetLevel(this->MILDigID,M_SATURATION_REF,saturation/2.0);
968 }
969 
970 //----------------------------------------------------------------------------
SetBlackLevel(float black)971 void vtkMILVideoSource::SetBlackLevel(float black)
972 {
973   if (this->BlackLevel == black)
974   {
975     return;
976   }
977 
978   this->BlackLevel = black;
979   this->Modified();
980 
981   vtkMILVideoSourceSetLevel(this->MILDigID,M_BLACK_REF,black/255);
982 }
983 
984 //----------------------------------------------------------------------------
SetWhiteLevel(float white)985 void vtkMILVideoSource::SetWhiteLevel(float white)
986 {
987   if (this->WhiteLevel == white)
988   {
989     return;
990   }
991 
992   this->WhiteLevel = white;
993   this->Modified();
994 
995   vtkMILVideoSourceSetLevel(this->MILDigID,M_WHITE_REF,white/255);
996 }
997 
998 //----------------------------------------------------------------------------
AllocateMILDigitizer()999 void vtkMILVideoSource::AllocateMILDigitizer()
1000 {
1001   char *format = "M_NTSC";
1002   int recording = this->Recording;
1003 
1004   if (this->MILDigID)
1005   {
1006     if (recording)
1007     {
1008       this->Stop();
1009     }
1010   }
1011 
1012   if (this->MILDigID != 0)
1013   {
1014     MdigFree(this->MILDigID);
1015   }
1016 
1017   switch (this->VideoFormat)
1018   {
1019     case VTK_MIL_RS170:
1020       format = "M_RS170";
1021       if (this->VideoInput == VTK_MIL_RGB)
1022       {
1023         format = "M_RS170_VIA_RGB";
1024       }
1025       break;
1026     case VTK_MIL_NTSC:
1027       format = "M_NTSC";
1028       if (this->VideoInput == VTK_MIL_YC)
1029       {
1030         format = "M_NTSC_YC";
1031       }
1032       if (this->VideoInput == VTK_MIL_RGB)
1033       {
1034         format = "M_NTSC_RGB";
1035       }
1036       break;
1037     case VTK_MIL_CCIR:
1038       format = "M_CCIR";
1039       if (this->VideoInput == VTK_MIL_RGB)
1040       {
1041         format = "M_CCIR_VIA_RGB";
1042       }
1043       this->FrameMaxSize[0] = 768;
1044       this->FrameMaxSize[1] = 576;
1045       break;
1046     case VTK_MIL_PAL:
1047     case VTK_MIL_SECAM:
1048       format = "M_PAL";
1049       if (this->VideoInput == VTK_MIL_YC)
1050       {
1051         format = "M_PAL_YC";
1052       }
1053       if (this->VideoInput == VTK_MIL_RGB)
1054       {
1055         format = "M_PAL_RGB";
1056       }
1057       this->FrameMaxSize[0] = 768;
1058       this->FrameMaxSize[1] = 576;
1059       break;
1060     case VTK_MIL_NONSTANDARD:
1061       this->FrameMaxSize[0] = 0;
1062       this->FrameMaxSize[1] = 0;
1063       break;
1064     default:
1065       vtkWarningMacro(<< "AllocateMILDigitizer: Unknown video format");
1066   }
1067 
1068   if (this->MILDigitizerDCF)
1069   {
1070     format = this->MILDigitizerDCF;
1071   }
1072 
1073   this->MILDigID = MdigAlloc(this->MILSysID,this->MILDigitizerNumber,format,
1074                              M_DEFAULT,M_NULL);
1075 
1076   if (this->MILDigID == 0)
1077   {
1078     vtkErrorMacro(<< "AllocateMILDigitizer:  Couldn't allocate MIL Digitizer\n");
1079     return;
1080   }
1081 
1082   vtkMILVideoSourceSetSize(this->MILDigID,this->FrameSize,this->FrameMaxSize);
1083 
1084   vtkMILVideoSourceSetChannel(this->MILDigID,this->VideoChannel);
1085 
1086   if (this->BrightnessLevel != 128)
1087   {
1088     vtkMILVideoSourceSetLevel(this->MILDigID,M_BRIGHTNESS_REF,
1089                               this->BrightnessLevel/255);
1090   }
1091   if (this->ContrastLevel != 1.0)
1092   {
1093     vtkMILVideoSourceSetLevel(this->MILDigID,M_CONTRAST_REF,
1094                               this->ContrastLevel/2.0);
1095   }
1096   if (this->HueLevel != 0.0)
1097   {
1098     vtkMILVideoSourceSetLevel(this->MILDigID,M_HUE_REF,
1099                               0.5+this->HueLevel);
1100   }
1101   if (this->SaturationLevel != 1.0)
1102   {
1103     vtkMILVideoSourceSetLevel(this->MILDigID,M_SATURATION_REF,
1104                               this->SaturationLevel/2.0);
1105   }
1106   if (this->BlackLevel != 0.0)
1107   {
1108     vtkMILVideoSourceSetLevel(this->MILDigID,M_BLACK_REF,
1109                               this->BlackLevel/255);
1110   }
1111   if (this->WhiteLevel != 255.0)
1112   {
1113     vtkMILVideoSourceSetLevel(this->MILDigID,M_WHITE_REF,
1114                               this->WhiteLevel/255);
1115   }
1116 
1117   if (this->MILDigID && this->MILBufID)
1118   {
1119     if (recording)
1120     {
1121       this->Record();
1122     }
1123   }
1124 }
1125 
1126 //----------------------------------------------------------------------------
AllocateMILBuffer()1127 void vtkMILVideoSource::AllocateMILBuffer()
1128 {
1129   int recording = this->Recording;
1130 
1131   if (this->MILDigID != 0)
1132   {
1133     if (recording)
1134     {
1135       this->Stop();
1136     }
1137   }
1138 
1139   if (this->MILBufID != 0)
1140   {
1141     MbufFree(this->MILBufID);
1142   }
1143 
1144   if (this->OutputFormat != VTK_LUMINANCE &&
1145       this->OutputFormat != VTK_RGB &&
1146       this->OutputFormat != VTK_RGBA)
1147   {
1148     vtkWarningMacro(<< "Initialize: unsupported OutputFormat");
1149     this->vtkVideoSource::SetOutputFormat(VTK_LUMINANCE);
1150   }
1151 
1152   if (this->OutputFormat == VTK_LUMINANCE)
1153   {
1154      this->MILBufID = MbufAlloc2d(this->MILSysID,this->FrameSize[0],
1155                                   this->FrameSize[1],
1156                                   8+M_UNSIGNED,M_IMAGE+M_GRAB,M_NULL);
1157   }
1158   else if (this->OutputFormat == VTK_RGB)
1159   {
1160     this->MILBufID = MbufAllocColor(this->MILSysID,3,this->FrameSize[0],
1161                                     this->FrameSize[1],
1162                                     8+M_UNSIGNED,M_IMAGE+M_GRAB+ \
1163                                     M_RGB24+M_PACKED,
1164                                     M_NULL);
1165   }
1166   else if (this->OutputFormat == VTK_RGBA)
1167   {
1168     this->MILBufID = MbufAllocColor(this->MILSysID,3,this->FrameSize[0],
1169                                     this->FrameSize[1],
1170                                     8+M_UNSIGNED,M_IMAGE+M_GRAB+M_RGB32+ \
1171                                     M_PACKED,
1172                                     M_NULL);
1173   }
1174 
1175   if (this->MILBufID == 0)
1176   {
1177     vtkErrorMacro(<< "AllocateMILBuffer:  Couldn't allocate MIL Buffer\n");
1178     return;
1179   }
1180 
1181   if (this->MILDigID != 0 && this->MILBufID != 0)
1182   {
1183     if (recording)
1184     {
1185       this->Record();
1186     }
1187   }
1188 }
1189 
1190 
1191 
1192