summaryrefslogtreecommitdiff
path: root/src/imaging/CMUCamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/imaging/CMUCamera.cpp')
-rw-r--r--src/imaging/CMUCamera.cpp466
1 files changed, 466 insertions, 0 deletions
diff --git a/src/imaging/CMUCamera.cpp b/src/imaging/CMUCamera.cpp
new file mode 100644
index 0000000..6c68c5f
--- /dev/null
+++ b/src/imaging/CMUCamera.cpp
@@ -0,0 +1,466 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#include "CMUCamera.h"
+#include "CMUCameraUtils.h"
+
+#include "../base/Exception.h"
+#include "../base/Logger.h"
+#include "../base/OSHelper.h"
+#include "../base/StringHelper.h"
+
+#include <windows.h>
+#include <1394Camera.h>
+
+using namespace std;
+
+namespace avg {
+
+CMUCamera::CMUCamera(long long guid, bool bFW800, IntPoint size,
+ PixelFormat camPF, PixelFormat destPF, float frameRate)
+ : Camera(camPF, destPF, size, frameRate),
+ m_WhitebalanceU(-1),
+ m_WhitebalanceV(-1),
+ m_pCamera(0)
+{
+ m_pCamera = new C1394Camera();
+ int err;
+ unsigned long videoFormat, videoMode;
+ getVideoFormatAndMode(getImgSize(), getCamPF(), &videoFormat, &videoMode);
+
+ // Find and open camera
+ if (m_pCamera->RefreshCameraList() <= 0) {
+ throw Exception(AVG_ERR_CAMERA_NONFATAL, "No Firewire cameras found");
+ }
+ int i = getCamIndex(guid);
+ err = m_pCamera->SelectCamera(i);
+ err = m_pCamera->InitCamera(TRUE);
+ AVG_ASSERT(err == CAM_SUCCESS);
+
+ if (bFW800) {
+ m_pCamera->Set1394b(true);
+ }
+
+ // Setup video format and rate
+ err = m_pCamera->SetVideoFormat(videoFormat);
+ checkCMUError(err, AVG_ERR_CAMERA_NONFATAL,
+ string("CMUCamera: Error setting video format ") + toString(videoFormat) +
+ ", mode: " + toString(videoMode));
+ err = m_pCamera->SetVideoMode(videoMode);
+ checkCMUError(err, AVG_ERR_CAMERA_NONFATAL,
+ string("CMUCamera: Error setting video mode ") + toString(videoMode) +
+ ", format: " + toString(videoFormat));
+ err = m_pCamera->SetVideoFrameRate(getFrameRateConst(getFrameRate()));
+ checkCMUError(err, AVG_ERR_CAMERA_NONFATAL, "Error setting frame rate");
+
+ // Start capturing images
+ err = m_pCamera->StartImageAcquisition();
+ if (err != CAM_SUCCESS) {
+ throw Exception(AVG_ERR_CAMERA_NONFATAL,
+ "CMUCamera: Could not start image acquisition. " +
+ CMUErrorToString(err));
+ }
+
+ // Set camera features
+ for (FeatureMap::iterator it=m_Features.begin(); it != m_Features.end(); it++) {
+ setFeature(it->first, it->second, true);
+ }
+ setWhitebalance(m_WhitebalanceU, m_WhitebalanceV, true);
+
+ if (camPF == BAYER8) {
+ char sModel[256], sVendor[256];
+ m_pCamera->GetCameraName(sModel, 256);
+ m_pCamera->GetCameraVendor(sVendor, 256);
+
+ if (strcmp(sModel, "DFx 31BF03") == 0) {
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO,
+ "Applying bayer pattern fixup for IS DFx31BF03 camera");
+ setCamPF(BAYER8_GRBG);
+ } else if (strcmp(sVendor, "Point Grey Research") == 0) {
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO,
+ "Applying bayer pattern fixup for PointGrey cameras");
+ enablePtGreyBayer();
+ }
+
+ }
+}
+
+CMUCamera::~CMUCamera()
+{
+ m_pCamera->StopImageAcquisition();
+ delete m_pCamera;
+}
+
+BitmapPtr CMUCamera::getImage(bool bWait)
+{
+ if (bWait) {
+ unsigned rc = WaitForSingleObject(m_pCamera->GetFrameEvent(), INFINITE);
+ AVG_ASSERT(rc == WAIT_OBJECT_0);
+ } else {
+ unsigned rc = WaitForSingleObject(m_pCamera->GetFrameEvent(), 0);
+ if (rc == WAIT_TIMEOUT) {
+ // No frame yet
+ return BitmapPtr();
+ }
+ AVG_ASSERT(rc == WAIT_OBJECT_0);
+ }
+ int rc2 = m_pCamera->AcquireImageEx(FALSE, NULL);
+ if (rc2 != CAM_SUCCESS) {
+ throw Exception(AVG_ERR_CAMERA_NONFATAL,
+ "CMUCamera: Could not acquire image from camera. " +
+ CMUErrorToString(rc2));
+ }
+ unsigned long captureBufferLength;
+ unsigned char* pCaptureBuffer = m_pCamera->GetRawData(&captureBufferLength);
+
+ BitmapPtr pCamBmp(new Bitmap(getImgSize(), getCamPF(), pCaptureBuffer,
+ captureBufferLength / getImgSize().y, false, "TempCameraBmp"));
+ return convertCamFrameToDestPF(pCamBmp);
+}
+
+
+const string& CMUCamera::getDevice() const
+{
+ return m_sDevice;
+}
+
+const std::string& CMUCamera::getDriverName() const
+{
+ static string sDriverName = "CMU 1394 Digital Camera Driver";
+ return sDriverName;
+}
+
+int CMUCamera::getFeature(CameraFeature Feature) const
+{
+ unsigned short val1;
+ unsigned short val2;
+ internalGetFeature(Feature, &val1, &val2);
+ return val1;
+}
+
+void CMUCamera::setFeature(CameraFeature Feature, int Value, bool bIgnoreOldValue)
+{
+ if (bIgnoreOldValue || m_Features[Feature] != Value) {
+ m_Features[Feature] = Value;
+ if (Feature == CAM_FEATURE_STROBE_DURATION) {
+ if (m_pCamera->HasStrobe()) {
+ C1394CameraControlStrobe* pControl = m_pCamera->GetStrobeControl(0);
+ int err = pControl->SetValue(Value);
+ checkCMUWarning(err == CAM_SUCCESS, "Error setting camera strobe.");
+ } else {
+ AVG_LOG_WARNING("Camera does not support strobe.");
+ }
+ } else {
+ CAMERA_FEATURE cmuFeature = getFeatureID(Feature);
+ if (m_pCamera->HasFeature(cmuFeature)) {
+ bool bAuto = (Value == -1);
+
+ C1394CameraControl* pControl = m_pCamera->GetCameraControl(cmuFeature);
+ int err1 = pControl->SetAutoMode(bAuto);
+ int err2 = CAM_SUCCESS;
+ if (!bAuto) {
+ err2 = pControl->SetValue(Value);
+ }
+ checkCMUWarning(err1 == CAM_SUCCESS && err2 == CAM_SUCCESS,
+ string("Error setting camera feature: ") +
+ cameraFeatureToString(Feature));
+ } else {
+ AVG_LOG_WARNING(string("Camera does not support feature: ") +
+ cameraFeatureToString(Feature));
+ }
+ }
+ }
+}
+
+void CMUCamera::setFeatureOneShot(CameraFeature Feature)
+{
+ CAMERA_FEATURE cmuFeature = getFeatureID(Feature);
+ if (cmuFeature != FEATURE_INVALID_FEATURE && m_pCamera->HasFeature(cmuFeature)) {
+ C1394CameraControl* pControl = m_pCamera->GetCameraControl(cmuFeature);
+ int err1 = pControl->SetOnOff(false);
+ int err2 = pControl->SetAutoMode(false);
+ int err3 = pControl->SetOnePush(true);
+ checkCMUWarning(err1 == CAM_SUCCESS && err2 == CAM_SUCCESS
+ && err3 == CAM_SUCCESS,
+ string("Error setting feature: ") + cameraFeatureToString(Feature));
+ } else {
+ AVG_LOG_WARNING(string("Camera does not support feature: ") +
+ cameraFeatureToString(Feature));
+ }
+}
+
+int CMUCamera::getWhitebalanceU() const
+{
+ unsigned short val1;
+ unsigned short val2;
+ internalGetFeature(CAM_FEATURE_WHITE_BALANCE, &val1, &val2);
+ return val1;
+}
+
+int CMUCamera::getWhitebalanceV() const
+{
+ unsigned short val1;
+ unsigned short val2;
+ internalGetFeature(CAM_FEATURE_WHITE_BALANCE, &val1, &val2);
+ return val2;
+}
+
+void CMUCamera::setWhitebalance(int u, int v, bool bIgnoreOldValue)
+{
+ if (bIgnoreOldValue || m_WhitebalanceU != u || m_WhitebalanceV != v) {
+ m_WhitebalanceU = u;
+ m_WhitebalanceV = v;
+ CAMERA_FEATURE cmuFeature = getFeatureID(CAM_FEATURE_WHITE_BALANCE);
+ if (m_pCamera->HasFeature(FEATURE_WHITE_BALANCE)) {
+ bool bAuto = (u == -1);
+
+ C1394CameraControl* pControl = m_pCamera->GetCameraControl(cmuFeature);
+ int err1 = pControl->SetAutoMode(bAuto);
+ int err2 = CAM_SUCCESS;
+ if (!bAuto) {
+ err2 = pControl->SetValue(u, v);
+ }
+ checkCMUWarning(err1 == CAM_SUCCESS && err2 == CAM_SUCCESS,
+ string("Error setting camera feature: ") +
+ cameraFeatureToString(CAM_FEATURE_WHITE_BALANCE));
+ } else {
+ AVG_LOG_WARNING(string("Camera does not support feature: ") +
+ cameraFeatureToString(CAM_FEATURE_WHITE_BALANCE));
+ }
+ }
+}
+
+int CMUCamera::countCameras()
+{
+ C1394Camera* pCamera = new C1394Camera();
+ if (pCamera->RefreshCameraList() <= 0) {
+ return 0;
+ }
+ int numCameras = pCamera->GetNumberCameras();
+ return numCameras;
+}
+
+CameraInfo* CMUCamera::getCameraInfos(int deviceNumber)
+{
+#ifdef AVG_ENABLE_CMU1394
+ C1394Camera* pCamera = new C1394Camera();
+ int err = pCamera->RefreshCameraList();
+ if (err <= 0) {
+ return 0;
+ }
+
+ err = pCamera->SelectCamera(deviceNumber);
+ if (err != CAM_SUCCESS) {
+ AVG_ASSERT(false);
+ }
+ pCamera->InitCamera(true);
+
+ long long uniqueID;
+ pCamera->GetCameraUniqueID((PLARGE_INTEGER)&uniqueID);
+ stringstream deviceID;
+ deviceID << uniqueID;
+
+ CameraInfo* pCamInfo = new CameraInfo("Firewire", deviceID.str());
+ getCameraImageFormats(pCamera, pCamInfo);
+ getCameraControls(pCamera, pCamInfo);
+
+ delete pCamera;
+ return pCamInfo;
+#endif
+ return NULL;
+}
+
+void CMUCamera::getCameraImageFormats(C1394Camera* pCamera, CameraInfo* pCamInfo)
+{
+ //Iterate over formats (up to 3 formats are supported)
+ for (int format = 0; format <= 2; format++) {
+ BOOL hasFormat = false;
+ hasFormat = pCamera->HasVideoFormat(format);
+ if(!hasFormat){
+ continue;
+ }
+ //Iterate over modes (up to 8 modes are supported)
+ for (int mode = 0; mode <= 7; mode++) {
+ BOOL hasMode = false;
+ hasMode = pCamera->HasVideoMode(format, mode);
+ if (!hasMode) {
+ continue;
+ }
+ //Ignore not libavg supported formats
+ if (mode == 0 && format == 0) {
+ continue;
+ }
+
+ IntPoint size;
+ PixelFormat pixelFormat;
+ FrameratesVector framerates;
+
+ getImageSizeAndPF(format, mode, size, pixelFormat);
+ getCameraFramerates(pCamera, format, mode, framerates);
+
+ CameraImageFormat imageFormat = CameraImageFormat(size, pixelFormat, framerates);
+ pCamInfo->addImageFormat(imageFormat);
+ }
+ }
+}
+
+void CMUCamera::getCameraFramerates(C1394Camera* pCamera, unsigned long videoFormat, unsigned long videoMode, FrameratesVector &framerates)
+{
+ for (int itFramerate = 0; itFramerate <= 7; itFramerate++) {
+ BOOL hasFramerate = false;
+ hasFramerate = pCamera->HasVideoFrameRate(videoFormat, videoMode, itFramerate);
+ if (!hasFramerate) {
+ continue;
+ }
+
+ float framerate = getFrameRateFloat(itFramerate);
+ framerates.push_back(framerate);
+ }
+}
+
+void CMUCamera::getCameraControls(C1394Camera* pCamera, CameraInfo* pCamInfo)
+{
+ //Iterate over amount of possible Features (up to 24 in CMU1394 DCD 6.4.5.240)
+ for (int indexFeature = 0; indexFeature <= 23; indexFeature++) {
+ C1394CameraControl* feature = pCamera->GetCameraControl((CAMERA_FEATURE)indexFeature);
+ if (feature == NULL) {
+ continue;
+ }
+ bool hasFeature = pCamera->HasFeature((CAMERA_FEATURE)indexFeature);
+ if (!hasFeature) {
+ continue;
+ }
+ //FrameRate (also known as TransferRate) is not supported
+ if (feature->GetFeatureID() == FEATURE_FRAME_RATE) {
+ continue;
+ }
+
+ std::string featureName = feature->GetName();
+ unsigned short min = -1;
+ unsigned short max = -1;
+ feature->GetRange(&min, &max);
+ unsigned short value_low = -1;
+ unsigned short value_high = -1; //TODO: For Whitebalance or Temperature etc.
+ feature->GetValue(&value_low, &value_high);
+ CameraControl camControl = CameraControl(featureName, (int)min, (int)max, (int)value_low);
+ pCamInfo->addControl(camControl);
+ }
+}
+
+int CMUCamera::getCamIndex(long long guid)
+{
+ if (guid == 0) {
+ return 0;
+ } else {
+ for (int i=0; i<m_pCamera->GetNumberCameras(); ++i) {
+ m_pCamera->SelectCamera(i);
+ long long camGuid;
+ m_pCamera->GetCameraUniqueID((PLARGE_INTEGER)&camGuid);
+ if (camGuid == guid) {
+ return i;
+ }
+ }
+ AVG_LOG_WARNING(string("Camera with guid ") + toString(guid)
+ + " not present. Using first camera.");
+ return 0;
+ }
+}
+
+void CMUCamera::internalGetFeature(CameraFeature Feature, unsigned short* val1,
+ unsigned short* val2) const
+{
+ *val1 = -1;
+ *val2 = -1;
+ CAMERA_FEATURE cmuFeature = getFeatureID(Feature);
+ if (m_pCamera->HasFeature(cmuFeature)) {
+ C1394CameraControl* pControl = m_pCamera->GetCameraControl(cmuFeature);
+ pControl->Status();
+ pControl->GetValue(val1, val2);
+ } else {
+ AVG_LOG_WARNING(string("Error reading camera feature: ") +
+ cameraFeatureToString(Feature));
+ }
+}
+
+void CMUCamera::enablePtGreyBayer()
+{
+ int err;
+ unsigned long advOffset = m_pCamera->GetAdvancedFeatureOffset();
+
+ unsigned long imageDataFormat;
+ err = m_pCamera->ReadQuadlet(advOffset+0x48, &imageDataFormat);
+ AVG_ASSERT(err == CAM_SUCCESS);
+ if (imageDataFormat & 0x80000000) {
+ err = m_pCamera->WriteQuadlet(advOffset+0x48, 0x80000081);
+ AVG_ASSERT(err == CAM_SUCCESS);
+ unsigned long bayerFormat;
+ err = m_pCamera->ReadQuadlet(advOffset+0x40, &bayerFormat);
+ AVG_ASSERT(err == CAM_SUCCESS);
+ PixelFormat exactPF = fwBayerStringToPF(bayerFormat);
+ setCamPF(exactPF);
+ } else {
+ AVG_LOG_ERROR("imageDataFormat not supported.");
+ }
+}
+
+void CMUCamera::checkCMUError(int code, int type, const string & sMsg) const
+{
+ if (code != CAM_SUCCESS) {
+ throw Exception(type, sMsg);
+ }
+}
+
+void CMUCamera::checkCMUWarning(bool bOk, const string& sMsg) const
+{
+ if (!bOk) {
+ AVG_LOG_WARNING(sMsg);
+ }
+}
+
+string CMUCamera::CMUErrorToString(int code)
+{
+ if (code == CAM_ERROR) {
+ return "WinI/O returned: " + getWinErrMsg(GetLastError());
+ }
+ string msg = "1394Camera returned: ";
+ switch (code) {
+ case CAM_ERROR_UNSUPPORTED:
+ return msg + "CAM_ERROR_UNSUPPORTED.";
+ case CAM_ERROR_NOT_INITIALIZED:
+ return msg + "CAM_ERROR_NOT_INITIALIZED.";
+ case CAM_ERROR_INVALID_VIDEO_SETTINGS:
+ return msg + "CAM_ERROR_INVALID_VIDEO_SETTINGS.";
+ case CAM_ERROR_BUSY:
+ return msg + "CAM_ERROR_BUSY.";
+ case CAM_ERROR_INSUFFICIENT_RESOURCES:
+ return msg + "CAM_ERROR_INSUFFICIENT_RESOURCES.";
+ case CAM_ERROR_PARAM_OUT_OF_RANGE:
+ return msg + "CAM_ERROR_PARAM_OUT_OF_RANGE.";
+ case CAM_ERROR_FRAME_TIMEOUT:
+ return msg + "CAM_ERROR_FRAME_TIMEOUT.";
+ default:
+ return msg + "unknown error.";
+ }
+}
+
+}