diff options
Diffstat (limited to 'src/player/CameraNode.cpp')
-rw-r--r-- | src/player/CameraNode.cpp | 414 |
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; +} + + +} |