Skip to content

Commit f8f4f9a

Browse files
committed
ENH: Add interface for specifying camera control parameters with Microsoft Media foundation device
This commit creates a generic base class vtkPlusParameters from vtkPlusUsImagingParameters that is now used for both ultrasound and camera control parameters. The new camera control parameters class contains the ability to set camera properties from the config file, and eventually through commands. Camera control properties are: - PanDegrees - TiltDegrees - RollDegrees - ZoomMm - IrisFStop - ExposureLog2Seconds - AutoExposure - FocusMm - AutoFocus Example config file element: ``` <CameraControlParameters> <Parameter Name="AutoExposure" Value="True"/> <Parameter Name="AutoFocus" Value="False"/> <Parameter Name="FocusMm" Value="100"/> <Parameter Name="ExposureLog2Seconds" Value="-3"/> </CameraControlParameters> ``` Not that not all parameters will be adjustable for all cameras.
1 parent 03db8a5 commit f8f4f9a

9 files changed

Lines changed: 851 additions & 297 deletions

src/PlusDataCollection/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ SET(Common_SRCS
130130
vtkFcsvReader.cxx
131131
vtkFcsvWriter.cxx
132132
vtkPlusBuffer.cxx
133+
vtkPlusParameters.cxx
134+
vtkPlusCameraControlParameters.cxx
133135
vtkPlusUsImagingParameters.cxx
134136
)
135137
SET(Virtual_SRCS
@@ -172,6 +174,8 @@ SET(Common_HDRS
172174
vtkFcsvReader.h
173175
vtkFcsvWriter.h
174176
vtkPlusBuffer.h
177+
vtkPlusParameters.h
178+
vtkPlusCameraControlParameters.h
175179
vtkPlusUsImagingParameters.h
176180
)
177181
SET(Miscellaneous_HDRS

src/PlusDataCollection/MicrosoftMediaFoundation/vtkPlusMmfVideoSource.cxx

Lines changed: 191 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Authors include: Adam Rankin
1515
// Local includes
1616
#include "PlusConfigure.h"
1717
#include "PixelCodec.h"
18+
#include "vtkPlusCameraControlParameters.h"
1819
#include "vtkPlusChannel.h"
1920
#include "vtkPlusDataSource.h"
2021
#include "vtkPlusMmfVideoSource.h"
@@ -36,6 +37,7 @@ Authors include: Adam Rankin
3637
// Windows includes
3738
#include <lmerr.h>
3839
#include <shlwapi.h>
40+
#include <strmif.h>
3941
#include <tchar.h>
4042
#include <windows.h>
4143

@@ -44,7 +46,7 @@ Authors include: Adam Rankin
4446
namespace
4547
{
4648
const unsigned int DEFAULT_DEVICE_ID = 0;
47-
const FrameSizeType DEFAULT_FRAME_SIZE = {640, 480, 1};
49+
const FrameSizeType DEFAULT_FRAME_SIZE = { 640, 480, 1 };
4850
const double DEFAULT_ACQUISITION_RATE = 30;
4951
const std::wstring DEFAULT_PIXEL_TYPE_NAME = L"YUY2";
5052
const GUID DEFAULT_PIXEL_TYPE = MFVideoFormat_YUY2; // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa370819(v=vs.85).aspx
@@ -174,7 +176,7 @@ STDMETHODIMP MmfVideoSourceReader::OnReadSample(HRESULT hrStatus, DWORD dwStream
174176
UINT32 actualHeight = 0;
175177
::MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &actualWidth, &actualHeight);
176178
if (actualWidth != this->PlusDevice->ActiveVideoFormat.FrameSize[0] ||
177-
actualHeight != this->PlusDevice->ActiveVideoFormat.FrameSize[1])
179+
actualHeight != this->PlusDevice->ActiveVideoFormat.FrameSize[1])
178180
{
179181
LOG_ERROR("Unexpected frame size: " << actualWidth << "x" << actualHeight << " (expected: " << this->PlusDevice->ActiveVideoFormat.FrameSize[0] << "x" << this->PlusDevice->ActiveVideoFormat.FrameSize[1] << ")");
180182
return S_FALSE;
@@ -246,6 +248,7 @@ vtkStandardNewMacro(vtkPlusMmfVideoSource);
246248
vtkPlusMmfVideoSource::vtkPlusMmfVideoSource()
247249
: FrameIndex(0)
248250
, Mutex(vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New())
251+
, CameraControlParameters(vtkSmartPointer<vtkPlusCameraControlParameters>::New())
249252
{
250253
this->MmfSourceReader = new MmfVideoSourceReader(this);
251254
this->RequireImageOrientationInConfiguration = true;
@@ -278,6 +281,8 @@ void vtkPlusMmfVideoSource::PrintSelf(ostream& os, vtkIndent indent)
278281
this->Superclass::PrintSelf(os, indent);
279282

280283
os << indent << "FrameIndex: " << (this->FrameIndex ? "On\n" : "Off\n");
284+
285+
this->CameraControlParameters->PrintSelf(os, indent.GetNextIndent());
281286
}
282287

283288
//----------------------------------------------------------------------------
@@ -305,12 +310,12 @@ PlusStatus vtkPlusMmfVideoSource::InternalConnect()
305310
}
306311

307312
if (!MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().SetupDevice(this->RequestedVideoFormat.DeviceId, this->RequestedVideoFormat.StreamIndex,
308-
this->RequestedVideoFormat.FrameSize[0], this->RequestedVideoFormat.FrameSize[1], this->AcquisitionRate, pixelFormat))
313+
this->RequestedVideoFormat.FrameSize[0], this->RequestedVideoFormat.FrameSize[1], this->AcquisitionRate, pixelFormat))
309314
{
310315
LOG_WARNING_W("Unable to init capture device with requested details:"
311-
<< " device ID: " << this->RequestedVideoFormat.DeviceId << " (" << GetRequestedDeviceName() << ") stream " << this->RequestedVideoFormat.StreamIndex
312-
<< ", " << this->RequestedVideoFormat.FrameSize[0] << "x" << this->RequestedVideoFormat.FrameSize[1]
313-
<< ", " << this->AcquisitionRate << "Hz, " << this->ActiveVideoFormat.PixelFormatName);
316+
<< " device ID: " << this->RequestedVideoFormat.DeviceId << " (" << GetRequestedDeviceName() << ") stream " << this->RequestedVideoFormat.StreamIndex
317+
<< ", " << this->RequestedVideoFormat.FrameSize[0] << "x" << this->RequestedVideoFormat.FrameSize[1]
318+
<< ", " << this->AcquisitionRate << "Hz, " << this->ActiveVideoFormat.PixelFormatName);
314319

315320
LogListOfCaptureVideoFormats(this->RequestedVideoFormat.DeviceId);
316321

@@ -328,9 +333,9 @@ PlusStatus vtkPlusMmfVideoSource::InternalConnect()
328333
this->ActiveVideoFormat.PixelFormatName = DEFAULT_PIXEL_TYPE_NAME;
329334

330335
LOG_INFO_W("Backing up to connecting with default capture settings:"
331-
<< " device ID: " << this->ActiveVideoFormat.DeviceId << " (" << GetActiveDeviceName() << ")"
332-
<< ", " << this->ActiveVideoFormat.FrameSize[0] << "x" << this->ActiveVideoFormat.FrameSize[1]
333-
<< ", " << DEFAULT_ACQUISITION_RATE << "Hz, " << this->ActiveVideoFormat.PixelFormatName);
336+
<< " device ID: " << this->ActiveVideoFormat.DeviceId << " (" << GetActiveDeviceName() << ")"
337+
<< ", " << this->ActiveVideoFormat.FrameSize[0] << "x" << this->ActiveVideoFormat.FrameSize[1]
338+
<< ", " << DEFAULT_ACQUISITION_RATE << "Hz, " << this->ActiveVideoFormat.PixelFormatName);
334339
}
335340

336341
this->MmfSourceReader->CaptureSource = MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().GetMediaSource(this->ActiveVideoFormat.DeviceId);
@@ -343,6 +348,12 @@ PlusStatus vtkPlusMmfVideoSource::InternalConnect()
343348
unsigned int frameRate = MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().GetFrameRate(this->ActiveVideoFormat.DeviceId);
344349
LOG_DEBUG_W("vtkPlusMmfVideoSource connected to device '" << GetActiveDeviceName() << "' at frame rate of " << frameRate << "Hz");
345350

351+
if (this->InternalApplyCameraControlParameterChange() == PLUS_FAIL)
352+
{
353+
LOG_ERROR("Failed to change imaging parameters in the device");
354+
return PLUS_FAIL;
355+
}
356+
346357
this->FrameIndex = 0;
347358

348359
return PLUS_SUCCESS;
@@ -394,7 +405,7 @@ PlusStatus vtkPlusMmfVideoSource::InternalStartRecording()
394405
if (FAILED(hr))
395406
{
396407
LOG_WARNING_W("Unable to set SourceReader output to requested format: " << this->RequestedVideoFormat.PixelFormatName
397-
<< ". Using device default.");
408+
<< ". Using device default.");
398409
}
399410
SafeRelease(&pDecodeType);
400411

@@ -485,7 +496,7 @@ PlusStatus vtkPlusMmfVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfi
485496
this->RequestedVideoFormat.StreamIndex = (DWORD)streamIndex;
486497
}
487498

488-
int requestedFrameSize[2] = {static_cast<int>(DEFAULT_FRAME_SIZE[0]), static_cast<int>(DEFAULT_FRAME_SIZE[1])};
499+
int requestedFrameSize[2] = { static_cast<int>(DEFAULT_FRAME_SIZE[0]), static_cast<int>(DEFAULT_FRAME_SIZE[1]) };
489500
if (deviceConfig->GetVectorAttribute("FrameSize", 2, requestedFrameSize))
490501
{
491502
if (requestedFrameSize[0] < 0 || requestedFrameSize[1] < 0)
@@ -505,6 +516,18 @@ PlusStatus vtkPlusMmfVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfi
505516
this->RequestedVideoFormat.PixelFormatName = std::wstring(attr.begin(), attr.end());
506517
}
507518

519+
XML_FIND_NESTED_ELEMENT_OPTIONAL(cameraParameters, deviceConfig, vtkPlusCameraControlParameters::CAMERA_CONTROL_XML_ELEMENT_TAG);
520+
if (cameraParameters != NULL)
521+
{
522+
this->CameraControlParameters->ReadConfiguration(deviceConfig);
523+
}
524+
525+
//vtkXMLDataElement* cameraControlElement = nullptr;
526+
//XML_FIND_NESTED_ELEMENT_OPTIONAL(cameraControlElement, deviceConfig, "CameraControl");
527+
//if (cameraControlElement)
528+
//{
529+
//}
530+
508531
return PLUS_SUCCESS;
509532
}
510533

@@ -527,6 +550,8 @@ PlusStatus vtkPlusMmfVideoSource::WriteConfiguration(vtkXMLDataElement* rootConf
527550
auto attr = std::string(this->RequestedVideoFormat.PixelFormatName.begin(), this->RequestedVideoFormat.PixelFormatName.end());
528551
deviceConfig->SetAttribute("VideoFormat", attr.c_str());
529552

553+
this->CameraControlParameters->WriteConfiguration(deviceConfig);
554+
530555
return PLUS_SUCCESS;
531556
}
532557

@@ -725,4 +750,159 @@ void vtkPlusMmfVideoSource::LogListOfCaptureDevices()
725750
std::wstring vtkPlusMmfVideoSource::GetCaptureDeviceName(unsigned int deviceId)
726751
{
727752
return MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().GetCaptureDeviceName(deviceId);
753+
}
754+
755+
//----------------------------------------------------------------------------
756+
PlusStatus vtkPlusMmfVideoSource::InternalApplyCameraControlParameterChange()
757+
{
758+
if (this->MmfSourceReader->CaptureSource == NULL)
759+
{
760+
LOG_ERROR("Cannot apply camera control parameter change, capture source is not initialized");
761+
return PLUS_FAIL;
762+
}
763+
764+
MfVideoCapture::CaptureDeviceParameters parameters =
765+
MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().GetParameters(this->ActiveVideoFormat.DeviceId);
766+
767+
////////////////////////////
768+
// Pan
769+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_PAN_DEGREES)
770+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_PAN_DEGREES))
771+
{
772+
double panDegrees = 0.0;
773+
if (this->CameraControlParameters->GetPanDegrees(panDegrees) != PLUS_SUCCESS)
774+
{
775+
LOG_ERROR("Failed to get pan camera control parameter");
776+
return PLUS_FAIL;
777+
}
778+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Pan].CurrentValue = panDegrees;
779+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_PAN_DEGREES, false);
780+
}
781+
782+
////////////////////////////
783+
// Tilt
784+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_TILT_DEGREES)
785+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_TILT_DEGREES))
786+
{
787+
double tiltDegrees = 0.0;
788+
if (this->CameraControlParameters->GetTiltDegrees(tiltDegrees) != PLUS_SUCCESS)
789+
{
790+
LOG_ERROR("Failed to get tilt camera control parameter");
791+
return PLUS_FAIL;
792+
}
793+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Tilt].CurrentValue = tiltDegrees;
794+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_TILT_DEGREES, false);
795+
}
796+
797+
////////////////////////////
798+
// Roll
799+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_ROLL_DEGREES)
800+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_ROLL_DEGREES))
801+
{
802+
double rollDegrees = 0.0;
803+
if (this->CameraControlParameters->GetRollDegrees(rollDegrees) != PLUS_SUCCESS)
804+
{
805+
LOG_ERROR("Failed to get roll camera control parameter");
806+
return PLUS_FAIL;
807+
}
808+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Roll].CurrentValue = rollDegrees;
809+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_ROLL_DEGREES, false);
810+
}
811+
812+
////////////////////////////
813+
// Zoom
814+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_ZOOM_MM)
815+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_ZOOM_MM))
816+
{
817+
double zoomMm = 0.0;
818+
if (this->CameraControlParameters->GetZoomMm(zoomMm) != PLUS_SUCCESS)
819+
{
820+
LOG_ERROR("Failed to get zoom camera control parameter");
821+
return PLUS_FAIL;
822+
}
823+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Zoom].CurrentValue = zoomMm;
824+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_ZOOM_MM, false);
825+
}
826+
827+
////////////////////////////
828+
// Iris
829+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_IRIS_FSTOP)
830+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_IRIS_FSTOP))
831+
{
832+
int irisFStop = 0.0;
833+
if (this->CameraControlParameters->GetIrisFStop(irisFStop) != PLUS_SUCCESS)
834+
{
835+
LOG_ERROR("Failed to get iris camera control parameter");
836+
return PLUS_FAIL;
837+
}
838+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Iris].CurrentValue = irisFStop;
839+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_IRIS_FSTOP, false);
840+
}
841+
842+
843+
////////////////////////////
844+
// Exposure
845+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_EXPOSURE_LOG2SECONDS)
846+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_EXPOSURE_LOG2SECONDS))
847+
{
848+
int exposureLog2Sec = 0.0;
849+
if (this->CameraControlParameters->GetExposureLog2Seconds(exposureLog2Sec) != PLUS_SUCCESS)
850+
{
851+
LOG_ERROR("Failed to get exposure camera control parameter");
852+
return PLUS_FAIL;
853+
}
854+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Exposure].CurrentValue = exposureLog2Sec;
855+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_EXPOSURE_LOG2SECONDS, false);
856+
}
857+
858+
////////////////////////////
859+
// AutoExposure
860+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_AUTO_EXPOSURE)
861+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_AUTO_EXPOSURE))
862+
{
863+
bool autoExposure = false;
864+
if (this->CameraControlParameters->GetAutoExposure(autoExposure) != PLUS_SUCCESS)
865+
{
866+
LOG_ERROR("Failed to get auto exposure camera control parameter");
867+
return PLUS_FAIL;
868+
}
869+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Exposure].Flag = autoExposure ? CameraControl_Flags_Auto : CameraControl_Flags_Manual;
870+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_AUTO_EXPOSURE, false);
871+
}
872+
873+
////////////////////////////
874+
// Focus
875+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_FOCUS_MM)
876+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_FOCUS_MM))
877+
{
878+
double focusMm = 0.0;
879+
if (this->CameraControlParameters->GetFocusMm(focusMm) != PLUS_SUCCESS)
880+
{
881+
LOG_ERROR("Failed to get focus camera control parameter");
882+
return PLUS_FAIL;
883+
}
884+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Focus].CurrentValue = focusMm;
885+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_FOCUS_MM, false);
886+
}
887+
888+
////////////////////////////
889+
// AutoFocus
890+
if (this->CameraControlParameters->IsSet(vtkPlusCameraControlParameters::KEY_AUTO_FOCUS)
891+
&& this->CameraControlParameters->IsPending(vtkPlusCameraControlParameters::KEY_AUTO_FOCUS))
892+
{
893+
bool autoFocus = false;
894+
if (this->CameraControlParameters->GetAutoFocus(autoFocus) != PLUS_SUCCESS)
895+
{
896+
LOG_ERROR("Failed to get auto focus camera control parameter");
897+
return PLUS_FAIL;
898+
}
899+
parameters.CameraControlParameters[MfVideoCapture::CaptureDeviceParameters::Focus].Flag = autoFocus ? CameraControl_Flags_Auto : CameraControl_Flags_Manual;
900+
this->CameraControlParameters->SetPending(vtkPlusCameraControlParameters::KEY_AUTO_FOCUS, false);
901+
}
902+
903+
////////////////////////////
904+
// Update the parameters
905+
MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().SetParameters(this->ActiveVideoFormat.DeviceId, parameters);
906+
907+
return PLUS_SUCCESS;
728908
}

src/PlusDataCollection/MicrosoftMediaFoundation/vtkPlusMmfVideoSource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Authors include: Danielle Pace
2525
#include <vtkSmartPointer.h>
2626

2727
class MmfVideoSourceReader;
28+
class vtkPlusCameraControlParameters;
2829

2930
/*!
3031
\class vtkPlusMmfVideoSource
@@ -96,13 +97,18 @@ class vtkPlusDataCollectionExport vtkPlusMmfVideoSource : public vtkPlusDevice
9697

9798
std::wstring GetCaptureDeviceName(unsigned int deviceId);
9899

100+
/*! Set changed camera control parameter to device */
101+
virtual PlusStatus InternalApplyCameraControlParameterChange();
102+
99103
int FrameIndex;
100104

101105
vtkSmartPointer<vtkIGSIORecursiveCriticalSection> Mutex;
102106
igsioVideoFrame UncompressedVideoFrame;
103107
VideoFormat RequestedVideoFormat;
104108
VideoFormat ActiveVideoFormat;
105109

110+
vtkSmartPointer<vtkPlusCameraControlParameters> CameraControlParameters;
111+
106112
MmfVideoSourceReader* MmfSourceReader;
107113
private:
108114
vtkPlusMmfVideoSource(const vtkPlusMmfVideoSource&); // Not implemented.

0 commit comments

Comments
 (0)