summaryrefslogtreecommitdiff
path: root/src/player/CameraNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/CameraNode.cpp')
-rw-r--r--src/player/CameraNode.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/src/player/CameraNode.cpp b/src/player/CameraNode.cpp
new file mode 100644
index 0000000..c091a4e
--- /dev/null
+++ b/src/player/CameraNode.cpp
@@ -0,0 +1,414 @@
+//
+// 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
+//
+
+#include "CameraNode.h"
+#include "OGLSurface.h"
+#include "TypeDefinition.h"
+
+#include "../base/Logger.h"
+#include "../base/Exception.h"
+#include "../base/ScopeTimer.h"
+#include "../base/XMLHelper.h"
+
+#include "../graphics/Filterfill.h"
+#include "../graphics/TextureMover.h"
+#include "../graphics/GLTexture.h"
+#include "../graphics/BitmapLoader.h"
+
+#include "../imaging/Camera.h"
+#include "../imaging/FWCamera.h"
+#include "../imaging/FakeCamera.h"
+
+#include <iostream>
+#include <sstream>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+using namespace std;
+
+namespace avg {
+
+void CameraNode::registerType()
+{
+ TypeDefinition def = TypeDefinition("camera", "rasternode",
+ ExportedObject::buildObject<CameraNode>)
+ .addArg(Arg<string>("driver", "firewire"))
+ .addArg(Arg<string>("device", ""))
+ .addArg(Arg<int>("unit", -1))
+ .addArg(Arg<bool>("fw800", false))
+ .addArg(Arg<float>("framerate", 15))
+ .addArg(Arg<int>("capturewidth", 640))
+ .addArg(Arg<int>("captureheight", 480))
+ .addArg(Arg<string>("pixelformat", "RGB"))
+ .addArg(Arg<int>("brightness", -1))
+ .addArg(Arg<int>("exposure", -1))
+ .addArg(Arg<int>("sharpness", -1))
+ .addArg(Arg<int>("saturation", -1))
+ .addArg(Arg<int>("camgamma", -1))
+ .addArg(Arg<int>("shutter", -1))
+ .addArg(Arg<int>("gain", -1))
+ .addArg(Arg<int>("strobeduration", -1));
+ TypeRegistry::get()->registerType(def);
+}
+
+CameraNode::CameraNode(const ArgList& args)
+ : m_bIsPlaying(false),
+ m_FrameNum(0),
+ m_bIsAutoUpdateCameraImage(true),
+ m_bNewBmp(false)
+{
+ args.setMembers(this);
+ string sDriver = args.getArgVal<string>("driver");
+ string sDevice = args.getArgVal<string>("device");
+ int unit = args.getArgVal<int>("unit");
+ bool bFW800 = args.getArgVal<bool>("fw800");
+ float frameRate = args.getArgVal<float>("framerate");
+ int width = args.getArgVal<int>("capturewidth");
+ int height = args.getArgVal<int>("captureheight");
+ string sPF = args.getArgVal<string>("pixelformat");
+
+ PixelFormat camPF = stringToPixelFormat(sPF);
+ if (camPF == NO_PIXELFORMAT) {
+ throw Exception(AVG_ERR_INVALID_ARGS, "Unknown camera pixel format "+sPF+".");
+ }
+ PixelFormat destPF;
+ if (pixelFormatIsColored(camPF)) {
+ if (BitmapLoader::get()->isBlueFirst()) {
+ destPF = B8G8R8X8;
+ } else {
+ destPF = R8G8B8X8;
+ }
+ } else {
+ destPF = I8;
+ }
+// cerr << "CameraNode ctor: " << camPF << "-->" << destPF << endl;
+
+ m_pCamera = createCamera(sDriver, sDevice, unit, bFW800, IntPoint(width, height),
+ camPF, destPF, frameRate);
+ AVG_TRACE(Logger::category::CONFIG,Logger::severity::INFO, "Got Camera " <<
+ m_pCamera->getDevice() << " from driver: " << m_pCamera->getDriverName());
+
+ m_pCamera->setFeature(CAM_FEATURE_BRIGHTNESS, args.getArgVal<int>("brightness"));
+ m_pCamera->setFeature(CAM_FEATURE_EXPOSURE, args.getArgVal<int>("exposure"));
+ m_pCamera->setFeature(CAM_FEATURE_SHARPNESS, args.getArgVal<int>("sharpness"));
+ m_pCamera->setFeature(CAM_FEATURE_SATURATION, args.getArgVal<int>("saturation"));
+ m_pCamera->setFeature(CAM_FEATURE_GAMMA, args.getArgVal<int>("camgamma"));
+ m_pCamera->setFeature(CAM_FEATURE_SHUTTER, args.getArgVal<int>("shutter"));
+ m_pCamera->setFeature(CAM_FEATURE_GAIN, args.getArgVal<int>("gain"));
+ m_pCamera->setFeature(CAM_FEATURE_STROBE_DURATION,
+ args.getArgVal<int>("strobeduration"));
+}
+
+CameraNode::~CameraNode()
+{
+ m_pCamera = CameraPtr();
+}
+
+void CameraNode::connectDisplay()
+{
+ RasterNode::connectDisplay();
+ if (m_bIsPlaying) {
+ open();
+ }
+}
+
+void CameraNode::connect(CanvasPtr pCanvas)
+{
+ if (!m_pCamera) {
+ throw Exception(AVG_ERR_UNSUPPORTED,
+ "Can't use camera node after disconnect(True).");
+ }
+ RasterNode::connect(pCanvas);
+}
+
+void CameraNode::disconnect(bool bKill)
+{
+ if (bKill) {
+ m_pCamera = CameraPtr();
+ }
+ RasterNode::disconnect(bKill);
+}
+
+void CameraNode::play()
+{
+ if (getState() == NS_CANRENDER) {
+ open();
+ }
+ m_bIsPlaying = true;
+}
+
+void CameraNode::stop()
+{
+ m_bIsPlaying = false;
+}
+
+bool CameraNode::isAvailable()
+{
+ if (!m_pCamera || boost::dynamic_pointer_cast<FakeCamera>(m_pCamera)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+int CameraNode::getBrightness() const
+{
+ return getFeature(CAM_FEATURE_BRIGHTNESS);
+}
+
+void CameraNode::setBrightness(int value)
+{
+ setFeature(CAM_FEATURE_BRIGHTNESS, value);
+}
+
+int CameraNode::getSharpness() const
+{
+ return getFeature(CAM_FEATURE_SHARPNESS);
+}
+
+void CameraNode::setSharpness(int value)
+{
+ setFeature(CAM_FEATURE_SHARPNESS, value);
+}
+
+int CameraNode::getSaturation() const
+{
+ return getFeature(CAM_FEATURE_SATURATION);
+}
+
+void CameraNode::setSaturation(int value)
+{
+ setFeature(CAM_FEATURE_SATURATION, value);
+}
+
+int CameraNode::getCamGamma() const
+{
+ return getFeature(CAM_FEATURE_GAMMA);
+}
+
+void CameraNode::setCamGamma(int value)
+{
+ setFeature(CAM_FEATURE_GAMMA, value);
+}
+
+int CameraNode::getShutter() const
+{
+ return getFeature(CAM_FEATURE_SHUTTER);
+}
+
+void CameraNode::setShutter(int value)
+{
+ setFeature(CAM_FEATURE_SHUTTER, value);
+}
+
+int CameraNode::getGain() const
+{
+ return getFeature(CAM_FEATURE_GAIN);
+}
+
+void CameraNode::setGain(int value)
+{
+ setFeature(CAM_FEATURE_GAIN, value);
+}
+
+int CameraNode::getWhitebalanceU() const
+{
+ return m_pCamera->getWhitebalanceU();
+}
+
+int CameraNode::getWhitebalanceV() const
+{
+ return m_pCamera->getWhitebalanceV();
+}
+
+void CameraNode::setWhitebalance(int u, int v)
+{
+ m_pCamera->setWhitebalance(u, v);
+}
+
+void CameraNode::doOneShotWhitebalance()
+{
+ // The first line turns off auto white balance.
+ m_pCamera->setWhitebalance(m_pCamera->getWhitebalanceU(),
+ m_pCamera->getWhitebalanceV());
+ m_pCamera->setFeatureOneShot(CAM_FEATURE_WHITE_BALANCE);
+}
+
+int CameraNode::getStrobeDuration() const
+{
+ return getFeature(CAM_FEATURE_STROBE_DURATION);
+}
+
+void CameraNode::setStrobeDuration(int value)
+{
+ setFeature(CAM_FEATURE_STROBE_DURATION, value);
+}
+
+
+IntPoint CameraNode::getMediaSize()
+{
+ return m_pCamera->getImgSize();
+}
+
+BitmapPtr CameraNode::getBitmap()
+{
+ if (m_pCurBmp) {
+ return m_pCurBmp;
+ } else {
+ throw Exception(AVG_ERR_CAMERA_NONFATAL,
+ "CameraNode.getBitmap: No camera image available.");
+ }
+}
+
+CamerasInfosVector CameraNode::getCamerasInfos()
+{
+ CamerasInfosVector camInfos = avg::getCamerasInfos();
+ return camInfos;
+}
+
+void CameraNode::resetFirewireBus()
+{
+ FWCamera::resetBus();
+}
+
+float CameraNode::getFPS() const
+{
+ return m_pCamera->getFrameRate();
+}
+
+void CameraNode::open()
+{
+ m_pCamera->startCapture();
+ setViewport(-32767, -32767, -32767, -32767);
+ PixelFormat pf = getPixelFormat();
+ IntPoint size = getMediaSize();
+ bool bMipmap = getMaterial().getUseMipmaps();
+ m_pTex = GLTexturePtr(new GLTexture(size, pf, bMipmap));
+ m_pTex->enableStreaming();
+ getSurface()->create(pf, m_pTex);
+ newSurface();
+
+ BitmapPtr pBmp = m_pTex->lockStreamingBmp();
+ if (pf == B8G8R8X8 || pf == B8G8R8A8) {
+ FilterFill<Pixel32> Filter(Pixel32(0,0,0,255));
+ Filter.applyInPlace(pBmp);
+ } else if (pf == I8) {
+ FilterFill<Pixel8> Filter(0);
+ Filter.applyInPlace(pBmp);
+ }
+ m_pTex->unlockStreamingBmp(true);
+ setupFX(true);
+}
+
+int CameraNode::getFeature(CameraFeature feature) const
+{
+ return m_pCamera->getFeature(feature);
+}
+
+void CameraNode::setFeature(CameraFeature feature, int value)
+{
+ m_pCamera->setFeature(feature, value);
+}
+
+int CameraNode::getFrameNum() const
+{
+ return m_FrameNum;
+}
+
+static ProfilingZoneID CameraFetchImage("Camera fetch image");
+static ProfilingZoneID CameraDownloadProfilingZone("Camera tex download");
+
+void CameraNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive,
+ float parentEffectiveOpacity)
+{
+ Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity);
+ if (isAutoUpdateCameraImage()) {
+ ScopeTimer Timer(CameraFetchImage);
+ updateToLatestCameraImage();
+ }
+ if (m_bNewBmp && isVisible()) {
+ ScopeTimer Timer(CameraDownloadProfilingZone);
+ m_FrameNum++;
+ BitmapPtr pBmp = m_pTex->lockStreamingBmp();
+ if (pBmp->getPixelFormat() != m_pCurBmp->getPixelFormat()) {
+ cerr << "Surface: " << pBmp->getPixelFormat() << ", CamDest: "
+ << m_pCurBmp->getPixelFormat() << endl;
+ }
+ AVG_ASSERT(pBmp->getPixelFormat() == m_pCurBmp->getPixelFormat());
+ pBmp->copyPixels(*m_pCurBmp);
+ m_pTex->unlockStreamingBmp(true);
+ renderFX(getSize(), Pixel32(255, 255, 255, 255), false);
+ m_bNewBmp = false;
+ }
+ calcVertexArray(pVA);
+}
+
+static ProfilingZoneID CameraProfilingZone("Camera::render");
+
+void CameraNode::render()
+{
+ if (m_bIsPlaying) {
+ ScopeTimer Timer(CameraProfilingZone);
+ blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode());
+ }
+}
+
+PixelFormat CameraNode::getPixelFormat()
+{
+ return m_pCamera->getDestPF();
+}
+
+void CameraNode::updateToLatestCameraImage()
+{
+ BitmapPtr pTmpBmp = m_pCamera->getImage(false);
+ while (pTmpBmp) {
+ m_bNewBmp = true;
+ m_pCurBmp = pTmpBmp;
+ pTmpBmp = m_pCamera->getImage(false);
+ }
+}
+
+void CameraNode::updateCameraImage()
+{
+ if (!isAutoUpdateCameraImage()) {
+ m_pCurBmp = m_pCamera->getImage(false);
+ blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode());
+ }
+}
+
+bool CameraNode::isAutoUpdateCameraImage() const
+{
+ return m_bIsAutoUpdateCameraImage;
+}
+
+void CameraNode::setAutoUpdateCameraImage(bool bVal)
+{
+ m_bIsAutoUpdateCameraImage = bVal;
+}
+
+bool CameraNode::isImageAvailable() const
+{
+ return m_pCurBmp.get() != NULL;
+}
+
+
+}