Skip to content

Commit 2753732

Browse files
committed
ENH: Add command to set MicrosoftMediaFoundation camera control parameters
1 parent 1d9524d commit 2753732

File tree

6 files changed

+412
-1
lines changed

6 files changed

+412
-1
lines changed

src/PlusDataCollection/MicrosoftMediaFoundation/vtkPlusMmfVideoSource.cxx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,17 @@ std::wstring vtkPlusMmfVideoSource::GetCaptureDeviceName(unsigned int deviceId)
746746
return MfVideoCapture::MediaFoundationVideoCaptureApi::GetInstance().GetCaptureDeviceName(deviceId);
747747
}
748748

749+
//----------------------------------------------------------------------------
750+
PlusStatus vtkPlusMmfVideoSource::SetNewCameraControlParameters(const vtkPlusCameraControlParameters& newCameraControlParameters)
751+
{
752+
this->CameraControlParameters->DeepCopy(newCameraControlParameters);
753+
if (this->IsConnected() && this->IsRecording())
754+
{
755+
// If we are connected and recording, apply the new camera control parameters immediately
756+
return this->InternalApplyCameraControlParameterChange();
757+
}
758+
}
759+
749760
//----------------------------------------------------------------------------
750761
PlusStatus vtkPlusMmfVideoSource::InternalApplyCameraControlParameterChange()
751762
{

src/PlusDataCollection/MicrosoftMediaFoundation/vtkPlusMmfVideoSource.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ Authors include: Danielle Pace
2121
#include "vtkPlusDevice.h"
2222
#include "vtkIGSIORecursiveCriticalSection.h"
2323

24+
// PlusDataCollection includes
25+
#include <vtkPlusCameraControlParameters.h>
26+
2427
// VTK includes
2528
#include <vtkSmartPointer.h>
2629

2730
class MmfVideoSourceReader;
28-
class vtkPlusCameraControlParameters;
2931

3032
/*!
3133
\class vtkPlusMmfVideoSource
@@ -73,6 +75,14 @@ class vtkPlusDataCollectionExport vtkPlusMmfVideoSource : public vtkPlusDevice
7375

7476
virtual bool IsTracker() const { return false; }
7577

78+
/*!
79+
Copy the new imaging parameters into the current parameter set
80+
It is up to subclasses to take the new imaging parameter set and apply it to their respective devices
81+
/param newImagingParameters class containing the new ultrasound imaging parameters
82+
*/
83+
virtual PlusStatus SetNewCameraControlParameters(const vtkPlusCameraControlParameters& newCameraControlParameters);
84+
vtkGetObjectMacro(CameraControlParameters, vtkPlusCameraControlParameters);
85+
7686
protected:
7787
/*! Constructor */
7888
vtkPlusMmfVideoSource();

src/PlusServer/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ IF(PLUS_USE_USDIGITALENCODERS_TRACKER)
8989
LIST(APPEND ${PROJECT_NAME}_HDRS Commands/vtkPlusUSDigitalEncoderCommand.h)
9090
ENDIF()
9191

92+
IF (PLUS_USE_MMF_VIDEO)
93+
LIST(APPEND ${PROJECT_NAME}_SRCS
94+
Commands/vtkPlusSetCameraControlParameterCommand.cxx
95+
#Commands/vtkPlusGetCameraControlParameterCommand.cxx
96+
)
97+
LIST(APPEND ${PROJECT_NAME}_HDRS
98+
Commands/vtkPlusSetCameraControlParameterCommand.h
99+
#Commands/vtkPlusGetCameraControlParameterCommand.h
100+
)
101+
ENDIF()
102+
92103
SET(${PROJECT_NAME}_INCLUDE_DIRS
93104
${CMAKE_CURRENT_SOURCE_DIR}
94105
${CMAKE_CURRENT_BINARY_DIR}
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
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+
#include "PlusConfigure.h"
8+
#include "vtkPlusSetCameraControlParameterCommand.h"
9+
10+
#include "vtkPlusDataCollector.h"
11+
#include "vtkObjectFactory.h"
12+
#include "vtkPlusChannel.h"
13+
#include "vtkPlusCommandProcessor.h"
14+
#include "vtkPlusCameraControlParameters.h"
15+
#include "vtkPlusMmfVideoSource.h"
16+
17+
#include <vtkVariant.h>
18+
#include <vtkSmartPointer.h>
19+
20+
#include <limits>
21+
#include <iterator>
22+
#include <string>
23+
24+
namespace
25+
{
26+
static const std::string SET_CAMERA_PARAMETER_CMD = "SetCameraControlParameters";
27+
}
28+
29+
vtkStandardNewMacro(vtkPlusSetCameraControlParameterCommand);
30+
31+
//----------------------------------------------------------------------------
32+
vtkPlusSetCameraControlParameterCommand::vtkPlusSetCameraControlParameterCommand()
33+
{
34+
this->CameraDeviceId = "";
35+
this->RequestedParameterChanges.clear();
36+
}
37+
38+
//----------------------------------------------------------------------------
39+
vtkPlusSetCameraControlParameterCommand::~vtkPlusSetCameraControlParameterCommand()
40+
{
41+
this->RequestedParameterChanges.clear();
42+
}
43+
44+
//----------------------------------------------------------------------------
45+
void vtkPlusSetCameraControlParameterCommand::SetNameToSetCameraControlParameter()
46+
{
47+
SetName(SET_CAMERA_PARAMETER_CMD);
48+
}
49+
50+
//----------------------------------------------------------------------------
51+
void vtkPlusSetCameraControlParameterCommand::PrintSelf(ostream& os, vtkIndent indent)
52+
{
53+
this->Superclass::PrintSelf(os, indent);
54+
}
55+
56+
//----------------------------------------------------------------------------
57+
void vtkPlusSetCameraControlParameterCommand::GetCommandNames(std::list<std::string>& cmdNames)
58+
{
59+
cmdNames.clear();
60+
cmdNames.push_back(SET_CAMERA_PARAMETER_CMD);
61+
}
62+
63+
//----------------------------------------------------------------------------
64+
std::string vtkPlusSetCameraControlParameterCommand::GetDescription(const std::string& commandName)
65+
{
66+
std::string desc;
67+
if (commandName.empty() || igsioCommon::IsEqualInsensitive(commandName, SET_CAMERA_PARAMETER_CMD))
68+
{
69+
desc += SET_CAMERA_PARAMETER_CMD;
70+
desc += ": Set camera image parameter. Attributes: CameraDeviceId: ID of the camera device.";
71+
}
72+
return desc;
73+
}
74+
75+
//----------------------------------------------------------------------------
76+
PlusStatus vtkPlusSetCameraControlParameterCommand::ReadConfiguration(vtkXMLDataElement* aConfig)
77+
{
78+
this->RequestedParameterChanges.clear();
79+
if (vtkPlusCommand::ReadConfiguration(aConfig) != PLUS_SUCCESS)
80+
{
81+
return PLUS_FAIL;
82+
}
83+
84+
this->SetCameraDeviceId(aConfig->GetAttribute("CameraDeviceId"));
85+
86+
// Parse nested elements and store requested parameter changes
87+
for (int elemIndex = 0; elemIndex < aConfig->GetNumberOfNestedElements(); ++elemIndex)
88+
{
89+
vtkXMLDataElement* currentElem = aConfig->GetNestedElement(elemIndex);
90+
if (igsioCommon::IsEqualInsensitive(currentElem->GetName(), "Parameter"))
91+
{
92+
const char* parameterName = currentElem->GetAttribute("Name");
93+
const char* parameterValue = currentElem->GetAttribute("Value");
94+
if (!parameterName || !parameterValue)
95+
{
96+
LOG_ERROR("Unable to find required Name or Value attribute in " << (currentElem->GetName() ? currentElem->GetName() : "(undefined)") << " element in SetUsParameter command");
97+
continue;
98+
}
99+
100+
this->RequestedParameterChanges[parameterName] = parameterValue;
101+
}
102+
}
103+
104+
return PLUS_SUCCESS;
105+
}
106+
107+
//----------------------------------------------------------------------------
108+
PlusStatus vtkPlusSetCameraControlParameterCommand::WriteConfiguration(vtkXMLDataElement* aConfig)
109+
{
110+
if (vtkPlusCommand::WriteConfiguration(aConfig) != PLUS_SUCCESS)
111+
{
112+
return PLUS_FAIL;
113+
}
114+
115+
XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(CameraDeviceId, aConfig);
116+
117+
// Write parameters as nested elements
118+
std::map<std::string, std::string>::iterator paramIt;
119+
for (paramIt = this->RequestedParameterChanges.begin(); paramIt != this->RequestedParameterChanges.end(); ++paramIt)
120+
{
121+
vtkSmartPointer<vtkXMLDataElement> paramElem = vtkSmartPointer<vtkXMLDataElement>::New();
122+
paramElem->SetName("Parameter");
123+
paramElem->SetAttribute("Name", paramIt->first.c_str());
124+
paramElem->SetAttribute("Value", paramIt->second.c_str());
125+
aConfig->AddNestedElement(paramElem);
126+
}
127+
128+
return PLUS_SUCCESS;
129+
}
130+
131+
//----------------------------------------------------------------------------
132+
PlusStatus vtkPlusSetCameraControlParameterCommand::Execute()
133+
{
134+
LOG_DEBUG("vtkPlusSetCameraControlParameterCommand::Execute: " << (!this->Name.empty() ? this->Name : "(undefined)")
135+
<< ", device: " << (this->CameraDeviceId.empty() ? "(undefined)" : this->CameraDeviceId));
136+
137+
if (this->Name.empty())
138+
{
139+
this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", "No command name specified.");
140+
return PLUS_FAIL;
141+
}
142+
else if (!igsioCommon::IsEqualInsensitive(this->Name, SET_CAMERA_PARAMETER_CMD))
143+
{
144+
this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", "Unknown command name: " + this->Name + ".");
145+
return PLUS_FAIL;
146+
}
147+
148+
vtkPlusMmfVideoSource* cameraDevice = vtkPlusMmfVideoSource::SafeDownCast(this->GetCameraDevice());
149+
if (cameraDevice == NULL)
150+
{
151+
this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", std::string("Device ")
152+
+ (this->CameraDeviceId.empty() ? "(undefined)" : this->CameraDeviceId) + std::string(" is not found."));
153+
return PLUS_FAIL;
154+
}
155+
156+
std::string cameraDeviceId = (cameraDevice->GetDeviceId().empty() ? "(unknown)" : cameraDevice->GetDeviceId());
157+
std::string resultString = "<CommandReply>";
158+
std::string error = "";
159+
std::map < std::string, std::pair<IANA_ENCODING_TYPE, std::string> > metaData;
160+
PlusStatus status = PLUS_SUCCESS;
161+
162+
vtkPlusCameraControlParameters* cameraControlParameters = cameraDevice->GetCameraControlParameters();
163+
164+
std::map<std::string, std::string>::iterator paramIt;
165+
for (paramIt = this->RequestedParameterChanges.begin(); paramIt != this->RequestedParameterChanges.end(); ++paramIt)
166+
{
167+
std::string parameterName = paramIt->first;
168+
std::string value = paramIt->second;
169+
resultString += "<Parameter Name=\"" + parameterName + "\"";
170+
171+
if (parameterName == vtkPlusCameraControlParameters::KEY_AUTO_EXPOSURE
172+
|| parameterName == vtkPlusCameraControlParameters::KEY_AUTO_FOCUS)
173+
{
174+
// boolean type parameter
175+
bool parameterValue = STRCASECMP(value.c_str(), "true") == 0;
176+
cameraControlParameters->SetValue<std::string>(parameterName, parameterValue ? "true" : "false");
177+
}
178+
else if (parameterName == vtkPlusCameraControlParameters::KEY_PAN_DEGREES
179+
|| parameterName == vtkPlusCameraControlParameters::KEY_TILT_DEGREES
180+
|| parameterName == vtkPlusCameraControlParameters::KEY_ROLL_DEGREES
181+
|| parameterName == vtkPlusCameraControlParameters::KEY_ZOOM_MM
182+
|| parameterName == vtkPlusCameraControlParameters::KEY_FOCUS_MM)
183+
{
184+
// double type parameter
185+
bool valid = false;
186+
double parameterValue = vtkVariant(value).ToDouble(&valid);
187+
if (!valid)
188+
{
189+
error += "Failed to parse " + parameterName + ". ";
190+
resultString += " Success=\"false\"/>";
191+
metaData[parameterName] = std::make_pair(IANA_TYPE_US_ASCII, "FAIL");
192+
status = PLUS_FAIL;
193+
continue;
194+
}
195+
cameraControlParameters->SetValue<double>(parameterName, parameterValue);
196+
}
197+
else if (parameterName == vtkPlusCameraControlParameters::KEY_EXPOSURE_LOG2SECONDS
198+
|| parameterName == vtkPlusCameraControlParameters::KEY_IRIS_FSTOP)
199+
{
200+
// integer type parameter
201+
bool valid = false;
202+
int parameterValue = vtkVariant(value).ToInt(&valid);
203+
if (!valid)
204+
{
205+
error += "Failed to parse " + parameterName + ". ";
206+
resultString += " Success=\"false\"/>";
207+
metaData[parameterName] = std::make_pair(IANA_TYPE_US_ASCII, "FAIL");
208+
status = PLUS_FAIL;
209+
continue;
210+
}
211+
cameraControlParameters->SetValue<int>(parameterName, parameterValue);
212+
}
213+
else
214+
{
215+
error += "Invalid parameter " + parameterName + ". ";
216+
resultString += " Success=\"false\"/>";
217+
metaData[parameterName] = std::make_pair(IANA_TYPE_US_ASCII, "FAIL");
218+
status = PLUS_FAIL;
219+
continue;
220+
}
221+
222+
if (cameraDevice->SetNewCameraControlParameters(*cameraControlParameters) == PLUS_FAIL)
223+
{
224+
error += "Failed to set " + parameterName + ". ";
225+
resultString += " Success=\"false\"/>";
226+
metaData[parameterName] = std::make_pair(IANA_TYPE_US_ASCII, "FAIL");
227+
status = PLUS_FAIL;
228+
continue;
229+
}
230+
231+
resultString += " Success=\"true\"/>";
232+
metaData[parameterName] = std::make_pair(IANA_TYPE_US_ASCII, "SUCCESS");
233+
} // For each parameter
234+
resultString += "</CommandReply>";
235+
236+
if (status != PLUS_SUCCESS)
237+
{
238+
LOG_WARNING("Failed to set US parameter, result string was: " << resultString);
239+
}
240+
241+
vtkSmartPointer<vtkPlusCommandRTSCommandResponse> commandResponse = vtkSmartPointer<vtkPlusCommandRTSCommandResponse>::New();
242+
commandResponse->UseDefaultFormatOff();
243+
commandResponse->SetClientId(this->ClientId);
244+
commandResponse->SetOriginalId(this->Id);
245+
commandResponse->SetDeviceName(this->DeviceName);
246+
commandResponse->SetCommandName(this->GetName());
247+
commandResponse->SetStatus(status);
248+
commandResponse->SetRespondWithCommandMessage(this->RespondWithCommandMessage);
249+
commandResponse->SetErrorString(error);
250+
commandResponse->SetResultString(resultString);
251+
commandResponse->SetParameters(metaData);
252+
this->CommandResponseQueue.push_back(commandResponse);
253+
254+
return status;
255+
}
256+
257+
//----------------------------------------------------------------------------
258+
vtkPlusDevice* vtkPlusSetCameraControlParameterCommand::GetCameraDevice()
259+
{
260+
vtkPlusDataCollector* dataCollector = GetDataCollector();
261+
if (dataCollector == NULL)
262+
{
263+
LOG_ERROR("Data collector is invalid");
264+
return NULL;
265+
}
266+
vtkPlusMmfVideoSource* cameraDevice = NULL;
267+
if (!this->CameraDeviceId.empty())
268+
{
269+
// Camera device ID is specified
270+
vtkPlusDevice* device = NULL;
271+
if (dataCollector->GetDevice(device, this->CameraDeviceId) != PLUS_SUCCESS)
272+
{
273+
LOG_ERROR("No camera device has been found by the name " << this->CameraDeviceId);
274+
return NULL;
275+
}
276+
// device found
277+
cameraDevice = dynamic_cast<vtkPlusMmfVideoSource*>(device);
278+
if (cameraDevice == NULL)
279+
{
280+
// wrong type
281+
LOG_ERROR("The specified device " << this->CameraDeviceId << " is not a camera device");
282+
return NULL;
283+
}
284+
}
285+
else
286+
{
287+
// No camera device id is specified, auto-detect the first one and use that
288+
for (DeviceCollectionConstIterator it = dataCollector->GetDeviceConstIteratorBegin(); it != dataCollector->GetDeviceConstIteratorEnd(); ++it)
289+
{
290+
cameraDevice = dynamic_cast<vtkPlusMmfVideoSource*>(*it);
291+
if (cameraDevice != NULL)
292+
{
293+
// found a camera device
294+
break;
295+
}
296+
}
297+
if (cameraDevice == NULL)
298+
{
299+
LOG_ERROR("No camera has been found");
300+
return NULL;
301+
}
302+
}
303+
return cameraDevice;
304+
}

0 commit comments

Comments
 (0)