Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
ofxDabVideoTracker/src/dab_tracker_camera.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
486 lines (398 sloc)
13.3 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** \file dab_tracker_camera.cpp | |
*/ | |
#include "dab_tracker_camera.h" | |
#include "ofxCvGrayscaleImage.h" | |
#include "ofxCvColorImage.h" | |
#include "ofxJSON.h" | |
#include "dab_tracker_serialize_helper.h" | |
#include "dab_tracker_image_save_queue.h" | |
using namespace dab; | |
using namespace dab::tracker; | |
float Camera::sFrameRate = 30.0; | |
Camera::Camera() | |
: mFrameSize( {640, 470} ) | |
, mChannelCount(3) | |
, mFrameRate(30.0) | |
, mSettingsFileName("Camera_Settings.json") | |
, mFrame(nullptr) | |
, mColorConversionFrame(nullptr) | |
, mMoviePlayer(nullptr) | |
, mMovieRecorder(nullptr) | |
, mMovieRecordFileName("capture") | |
, mMovieRecordFileSuffix("mp4") | |
, mBlocked(false) | |
, mCapturing(false) | |
, mLoadSettings(false) | |
, mSaveSettings(false) | |
, mMovieRecording(false) | |
, mMoviePlaying(false) | |
{ | |
mSelf = std::shared_ptr<Camera>(this); | |
createBaseParameters(); | |
} | |
Camera::Camera(std::array<unsigned int, 2> pFrameSize, unsigned int pChannelCount) throw (dab::Exception) | |
: mFrameSize(pFrameSize) | |
, mChannelCount(pChannelCount) | |
, mFrameRate(sFrameRate) | |
, mSettingsFileName("Camera_Settings.json") | |
, mFrame(nullptr) | |
, mColorConversionFrame(nullptr) | |
, mMoviePlayer(nullptr) | |
, mMovieRecorder(nullptr) | |
, mMovieRecordFileName("capture") | |
, mMovieRecordFileSuffix("mp4") | |
, mBlocked(false) | |
, mCapturing(false) | |
, mLoadSettings(false) | |
, mSaveSettings(false) | |
, mMovieRecording(false) | |
, mMoviePlaying(false) | |
{ | |
mSelf = std::shared_ptr<Camera>(this); | |
createBaseParameters(); | |
} | |
Camera::Camera(const std::string& pMoviePlayFileName, unsigned int pChannelCount, unsigned int pFrameRate) throw (dab::Exception) | |
: mMoviePlayFileName(pMoviePlayFileName) | |
, mChannelCount(pChannelCount) | |
, mFrameRate(pFrameRate) | |
, mSettingsFileName("Camera_Settings.json") | |
, mFrame(nullptr) | |
, mColorConversionFrame(nullptr) | |
, mMoviePlayer(nullptr) | |
, mMovieRecorder(nullptr) | |
, mBlocked(false) | |
, mCapturing(false) | |
, mLoadSettings(false) | |
, mSaveSettings(false) | |
, mMovieRecording(false) | |
, mMoviePlaying(true) | |
{ | |
mSelf = std::shared_ptr<Camera>(this); | |
bool success; | |
mMoviePlayer = new ofVideoPlayer(); | |
success = mMoviePlayer->load(mMoviePlayFileName); | |
if(success == false) throw dab::Exception("TRACKER ERROR: failed to load move file " + mMoviePlayFileName, __FILE__, __FUNCTION__, __LINE__); | |
if(mChannelCount == 1) | |
{ | |
mChannelCount = 1; | |
mFrame = new ofxCvGrayscaleImage(); | |
} | |
else if(mChannelCount == 3) | |
{ | |
mChannelCount = 3; | |
mFrame = new ofxCvColorImage(); | |
} | |
else throw dab::Exception("TRACKER ERROR: movie file " + mMoviePlayFileName + " has an unsupported color format", __FILE__, __FUNCTION__, __LINE__); | |
mFrameSize[0] = mMoviePlayer->getWidth(); | |
mFrameSize[1] = mMoviePlayer->getHeight(); | |
std::cout << "framerate " << mFrameRate << "\n"; | |
mMoviePlayer->setLoopState(OF_LOOP_NORMAL); | |
createBaseParameters(); | |
} | |
Camera::~Camera() throw (dab::Exception) | |
{ | |
if(mFrame != nullptr) delete mFrame; | |
for(auto controlIter = mControls.begin(); controlIter != mControls.end(); ++controlIter) | |
{ | |
delete controlIter->second; | |
} | |
mControls.clear(); | |
} | |
void | |
Camera::createBaseParameters() | |
{ | |
Parameter<bool>* recordingControl = new Parameter<bool>( "record", mMovieRecording); | |
recordingControl->registerParameterListener(mSelf); | |
mControls["record"] = recordingControl; | |
mDontSaveControlNames.push_back("record"); | |
Parameter<bool>* saveSettingsControl = new Parameter<bool>("savesettings", mSaveSettings); | |
saveSettingsControl->registerParameterListener(mSelf); | |
mControls["savesettings"] = saveSettingsControl; | |
mDontSaveControlNames.push_back("savesettings"); | |
Parameter<bool>* loadSettingsControl = new Parameter<bool>("loadsettings", mLoadSettings); | |
loadSettingsControl->registerParameterListener(mSelf); | |
mControls["loadsettings"] = loadSettingsControl; | |
mDontSaveControlNames.push_back("loadsettings"); | |
} | |
const array<unsigned int, 2>& | |
Camera::frameSize() const | |
{ | |
return mFrameSize; | |
} | |
void | |
Camera::setSettingsFileName(const std::string& pSettingsFileName) | |
{ | |
mSettingsFileName = pSettingsFileName; | |
} | |
void | |
Camera::setMovieRecordFileName( const std::string& pMovieRecordFileName ) | |
{ | |
mMovieRecordFileName = pMovieRecordFileName; | |
} | |
unsigned int | |
Camera::channelCount() const | |
{ | |
return mChannelCount; | |
} | |
float | |
Camera::frameRate() const | |
{ | |
return mFrameRate; | |
} | |
ofxCvImage* | |
Camera::frame() | |
{ | |
return mFrame; | |
} | |
bool | |
Camera::checkControl(const std::string& pControlName) const | |
{ | |
return mControls.find(pControlName) != mControls.end(); | |
} | |
bool | |
Camera::checkControlValue(const std::string& pControlName) const | |
{ | |
auto controlIter = mControls.find(pControlName); | |
if( controlIter == mControls.end() ) return false; | |
return controlIter->second->hasValue(); | |
} | |
std::map<std::string,AbstractParameter*>& | |
Camera::controls() | |
{ | |
return mControls; | |
} | |
const std::map<std::string, AbstractParameter*>& | |
Camera::controls() const | |
{ | |
return mControls; | |
} | |
AbstractParameter& | |
Camera::getControl(const std::string& pControlName ) throw (dab::Exception) | |
{ | |
auto controlIter = mControls.find(pControlName); | |
if( controlIter == mControls.end() ) throw dab::Exception("TRACKER ERROR: Camera has no control named " + pControlName, __FILE__, __FUNCTION__, __LINE__); | |
return *(controlIter->second); | |
} | |
const AbstractParameter& | |
Camera::getControl(const std::string& pControlName ) const throw (dab::Exception) | |
{ | |
auto controlIter = mControls.find(pControlName); | |
if( controlIter == mControls.end() ) throw dab::Exception("TRACKER ERROR: Camera has no control named " + pControlName, __FILE__, __FUNCTION__, __LINE__); | |
return *(controlIter->second); | |
} | |
const AbstractValue& | |
Camera::getControlValue(const std::string& pControlName) const throw (dab::Exception) | |
{ | |
auto controlIter = mControls.find(pControlName); | |
if( controlIter == mControls.end() ) throw dab::Exception("TRACKER ERROR: Camera has no control named " + pControlName, __FILE__, __FUNCTION__, __LINE__); | |
AbstractParameter* cameraControl = controlIter->second; | |
if(cameraControl->hasValue() == false) throw dab::Exception("TRACKER ERROR: Camera control " + pControlName + " has no value", __FILE__, __FUNCTION__, __LINE__); | |
return cameraControl->value(); | |
} | |
void | |
Camera::setControlValue(const std::string& pControlName) throw (dab::Exception) | |
{} | |
void | |
Camera::setControlValue(const std::string& pControlName, const AbstractValue& pValue ) throw (dab::Exception) | |
{ | |
auto controlIter = mControls.find(pControlName); | |
if( controlIter == mControls.end() ) throw dab::Exception("TRACKER ERROR: Camera has no control named " + pControlName, __FILE__, __FUNCTION__, __LINE__); | |
try | |
{ | |
if( pControlName == "record" ) | |
{ | |
bool controlValue = pValue.get<bool>(); | |
if( controlValue == true ) startRecording(); | |
else if( controlValue == false ) stopRecording(); | |
} | |
else if( pControlName == "savesettings" ) | |
{ | |
bool controlValue = pValue.get<bool>(); | |
mSaveSettings = true; | |
} | |
else if( pControlName == "loadsettings" ) | |
{ | |
bool controlValue = pValue.get<bool>(); | |
mLoadSettings = true; | |
} | |
} | |
catch(dab::Exception& e) | |
{ | |
throw; | |
} | |
} | |
void | |
Camera::notifyParameterChange( const AbstractParameter& pParameter ) | |
{ | |
//std::cout << "notifyParameterChange " << pParameter.name() << "\n"; | |
try | |
{ | |
if( pParameter.hasValue() == true ) setControlValue(pParameter.name(), pParameter.value()); | |
else setControlValue(pParameter.name()); | |
} | |
catch (dab::Exception& e) | |
{ | |
e += dab::Exception("TRACKER ERROR: notifyParameterChange failed for parameter " + pParameter.name() + "\n", __FILE__, __FUNCTION__, __LINE__); | |
std::cout << e << "\n"; | |
} | |
} | |
void | |
Camera::start() throw (dab::Exception) | |
{ | |
if(mMoviePlaying == true && mMoviePlayer != nullptr) | |
{ | |
mMoviePlayer->play(); | |
} | |
} | |
void | |
Camera::stop() throw (dab::Exception) | |
{ | |
if( mMoviePlaying == true && mMoviePlayer != nullptr) | |
{ | |
mMoviePlayer->stop(); | |
} | |
} | |
void | |
Camera::capture() throw (dab::Exception) | |
{ | |
bool isFrameNew; | |
bool success; | |
if(mLoadSettings == true) | |
{ | |
restoreSettings(); | |
mLoadSettings = false; | |
} | |
if(mSaveSettings == true) | |
{ | |
saveSettings(); | |
mSaveSettings = false; | |
} | |
if( mMoviePlaying == true && mMoviePlayer != nullptr) | |
{ | |
mMoviePlayer->update(); | |
isFrameNew = mMoviePlayer->isFrameNew(); | |
if(isFrameNew == true) | |
{ | |
if(mChannelCount == 1) // color to grayscale conversion necessary | |
{ | |
if(mColorConversionFrame == nullptr) | |
{ | |
mColorConversionFrame = new ofxCvColorImage(); | |
mColorConversionFrame->allocate( mFrameSize[0], mFrameSize[1] ); | |
} | |
mColorConversionFrame->setFromPixels( mMoviePlayer->getPixels().getData(), mFrameSize[0], mFrameSize[1] ); | |
*mFrame = *mColorConversionFrame; | |
} | |
else mFrame->setFromPixels( mMoviePlayer->getPixels().getData(), mFrameSize[0], mFrameSize[1] ); | |
} | |
} | |
if( mMovieRecording == true && isFrameNew == true) | |
{ | |
if(mChannelCount == 1) // color to grayscale conversion necessary | |
{ | |
if(mColorConversionFrame == nullptr) | |
{ | |
mColorConversionFrame = new ofxCvColorImage(); | |
mColorConversionFrame->allocate( mFrameSize[0], mFrameSize[1] ); | |
} | |
*mColorConversionFrame = *static_cast<ofxCvGrayscaleImage*>(mFrame); | |
success = mMovieRecorder->addFrame( mColorConversionFrame->getPixels() ); | |
} | |
else | |
{ | |
success = mMovieRecorder->addFrame( mFrame->getPixels() ); | |
} | |
if( success == false ) throw dab::Exception("TRACKER ERROR: failed to record camera frame", __FUNCTION__, __FUNCTION__, __LINE__); | |
//if( mMovieRecorder->hasVideoError() ) throw dab::Exception("TRACKER ERROR: failed to record camera frame", __FUNCTION__, __FUNCTION__, __LINE__); | |
} | |
if (mCaptureStill == true) | |
{ | |
saveStill(mFrame, "color_" + mCaptureStillFileName + ".bmp"); | |
mCaptureStill = false; | |
} | |
} | |
void | |
Camera::startRecording() throw (dab::Exception) | |
{ | |
if(mMovieRecording == true) return; | |
bool success; | |
if( mMovieRecorder == nullptr ) | |
{ | |
mMovieRecorder = new ofxVideoRecorder(); | |
mMovieRecorder->setFfmpegLocation("C:\\ffmpeg\\bin\\ffmpeg.exe"); | |
mMovieRecorder->setVideoCodec("mpeg4"); // mjpeg / h264 | |
//mMovieRecorder->setVideoBitrate("10000k"); | |
} | |
std::string fileName = mMovieRecordFileName + "_" + ofGetTimestampString() + "." + mMovieRecordFileSuffix; | |
success = mMovieRecorder->setup(fileName, mFrameSize[0], mFrameSize[1], mFrameRate); | |
if(success == false) throw dab::Exception("TRACKER ERROR: failed to start recording to file " + mMovieRecordFileName, __FILE__, __FUNCTION__, __LINE__); | |
mMovieRecorder->start(); | |
mMovieRecording = true; | |
} | |
void | |
Camera::stopRecording() throw (dab::Exception) | |
{ | |
if(mMovieRecording == false ) return; | |
mMovieRecorder->close(); | |
mMovieRecording = false; | |
} | |
void | |
Camera::recordStill(const std::string& pFileName) throw (dab::Exception) | |
{ | |
mCaptureStillFileName = pFileName; | |
mCaptureStill = true; | |
} | |
void | |
Camera::saveStill(ofxCvImage* pImage, const std::string& pFileName) throw (dab::Exception) | |
{ | |
ImageSaveQueue::get().addImage(pImage, pFileName); | |
} | |
void | |
Camera::saveSettings() throw (dab::Exception) | |
{ | |
std::cout << "save settings\n"; | |
SerializeHelper& serializeHelper = SerializeHelper::get(); | |
Json::Value jsonData; | |
try | |
{ | |
for( auto controlIter = mControls.begin(); controlIter != mControls.end(); controlIter++) | |
{ | |
AbstractParameter* cameraParameter = controlIter->second; | |
if( std::find(mDontSaveControlNames.begin(), mDontSaveControlNames.end(), cameraParameter->name() ) == mDontSaveControlNames.end() ) | |
{ | |
serializeHelper.addValue(jsonData, *cameraParameter); | |
} | |
} | |
serializeHelper.save(jsonData, mSettingsFileName); | |
} | |
catch (Exception& e) | |
{ | |
e += Exception("TRACKER ERROR: failed to save camera settings", __FILE__, __FUNCTION__, __LINE__); | |
throw e; | |
} | |
} | |
void | |
Camera::restoreSettings() throw (dab::Exception) | |
{ | |
std::cout << "load settings\n"; | |
SerializeHelper& serializeHelper = SerializeHelper::get(); | |
Json::Value jsonData; | |
try | |
{ | |
serializeHelper.restore(jsonData, mSettingsFileName); | |
for( auto controlIter = mControls.begin(); controlIter != mControls.end(); controlIter++) | |
{ | |
AbstractParameter* cameraParameter = controlIter->second; | |
const std::string& parameterName = cameraParameter->name(); | |
if(serializeHelper.hasValue(jsonData, *cameraParameter) == true) | |
{ | |
serializeHelper.getValue(jsonData, *cameraParameter); | |
} | |
} | |
} | |
catch (Exception& e) | |
{ | |
e += Exception("TRACKER ERROR: failed to restore camera settings", __FILE__, __FUNCTION__, __LINE__); | |
throw e; | |
} | |
} |