svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/CvContent.cpp
Go to the documentation of this file.
00001 #ifdef USE_OPENCV
00002 
00003 #include <Poco/DateTime.h>
00004 #include <Poco/Timezone.h>
00005 #include <Poco/Mutex.h>
00006 #include <Poco/Thread.h>
00007 #include <Poco/Runnable.h>
00008 #include <Poco/Stringtokenizer.h>
00009 #include <Poco/Util/XMLConfiguration.h>
00010 #include <Poco/UnicodeConverter.h>
00011 
00012 #include "CvContent.h"
00013 
00014 using Poco::Util::XMLConfiguration;
00015 
00016 
00017 CvContent::CvContent(Renderer& renderer, int splitType): Content(renderer, splitType), activeOpenDetectMovie(this, &CvContent::openDetectMovie),
00018     _normalItem(NULL), _normalMovie(NULL), _detectedItem(NULL), _detectedMovie(NULL),
00019     _fx(NULL), _small1(NULL), _small2(NULL), _diff(NULL), _diff2(NULL), _photo(NULL), 
00020     _detected(false), _doShutter(0), _viewPhoto(0), _finished(true), _playing(false), _statusFrame(0)
00021 {
00022     initialize();
00023     _scene = (CaptureScenePtr)_renderer.getScene("capture");
00024 }
00025 
00026 CvContent::‾CvContent() {
00027     initialize();
00028 }
00029 
00030 void CvContent::saveConfiguration() {
00031     try {
00032         Poco::Util::XMLConfiguration* xml = new Poco::Util::XMLConfiguration("cv-config.xml");
00033         if (xml) {
00034             xml->setInt("detect", _detectThreshold);
00035             xml->setInt("intervals[@diff]", _intervalDiff);
00036             xml->setInt("intervals[@small]", _intervalSmall);
00037             xml->setInt("clip[@x]", _clipX);
00038             xml->setInt("clip[@y]", _clipY);
00039             xml->setInt("clip[@w]", _clipW);
00040             xml->setInt("clip[@h]", _clipH);
00041             xml->save("cv-config.xml");
00042             xml->release();
00043             _log.information("cv parameters saved");
00044         }
00045     } catch (Poco::Exception& ex) {
00046         _log.warning(ex.displayText());
00047     }
00048 }
00049 
00050 void CvContent::initialize() {
00051     srand(time(NULL));
00052     close();
00053 }
00054 
00056 bool CvContent::open(const MediaItemPtr media, const int offset) {
00057     initialize();
00058 
00059     int deviceW = 0;
00060     int deviceH = 0;
00061     try {
00062         XMLConfiguration* xml = new XMLConfiguration("cv-config.xml");
00063 //      _deviceNo = xml->getInt("device[@no]", 0);
00064         deviceW = xml->getInt("device[@w]", 640);
00065         deviceH = xml->getInt("device[@h]", 480);
00066 //      _deviceFPS = xml->getInt("device[@fps]", 60);
00067         _subtract = xml->getDouble("subtract", 0.5);
00068 //      _samples = xml->getInt("samples", 4);
00069         _detectThreshold = xml->getInt("detect", 50);
00070         _intervalDiff = xml->getInt("intervals[@diff]", 60);
00071         _intervalSmall = xml->getInt("intervals[@small]", 12);
00072         _clipX = xml->getInt("clip[@x]", 0);
00073         _clipY = xml->getInt("clip[@y]", 0);
00074         _clipW = xml->getInt("clip[@w]", deviceW);
00075         _clipH = xml->getInt("clip[@h]", deviceH);
00076         _normalFile = xml->getString("normalMovie", "");
00077         string detectedFile = xml->getString("detectedMovie", "");
00078         Poco::StringTokenizer files(detectedFile, ",");
00079         for (Poco::StringTokenizer::Iterator it = files.begin(); it != files.end(); it++) {
00080             _detectFiles.push_back(*it);
00081         }
00082         _detectCount = xml->getInt("detectedMovie[@count]", 1);
00083 
00084         xml->release();
00085     } catch (Poco::Exception& ex) {
00086         _log.warning(ex.displayText());
00087     }
00088 
00089     vector<MediaItemFile> file1;
00090     file1.push_back(MediaItemFile(MediaTypeMovie, _normalFile, ""));
00091     _normalItem = new MediaItem(MediaTypeMovie, "normal", "normal", 0, false, file1);
00092     _normalMovie = new FFMovieContent(_renderer, config().splitType);
00093     if (_normalMovie->open(_normalItem)) {
00094         _normalMovie->setPosition(config().stageRect.left, config().stageRect.top);
00095         _normalMovie->setBounds(config().stageRect.right, config().stageRect.bottom);
00096         _normalMovie->play();
00097     } else {
00098         SAFE_DELETE(_normalMovie);
00099     }
00100 
00101     _detectedMovie = new FFMovieContent(_renderer, config().splitType);
00102     _detectedMovie->setPosition(config().stageRect.left, config().stageRect.top);
00103     _detectedMovie->setBounds(config().stageRect.right, config().stageRect.bottom);
00104     activeOpenDetectMovie();
00105 
00106     std::wstring wfile;
00107     Poco::UnicodeConverter::toUTF16(string("subbg.fx"), wfile);
00108     LPD3DXBUFFER errors = NULL;
00109     HRESULT hr = D3DXCreateEffectFromFile(_renderer.get3DDevice(), wfile.c_str(), 0, 0, D3DXSHADER_DEBUG, 0, &_fx, &errors);
00110     if (errors) {
00111         std::vector<char> text(errors->GetBufferSize());
00112         memcpy(&text[0], errors->GetBufferPointer(), errors->GetBufferSize());
00113         text.push_back('¥0');
00114         _log.warning(Poco::format("shader compile error: %s", string(&text[0])));
00115         SAFE_RELEASE(errors);
00116     } else if (FAILED(hr)) {
00117         _log.warning(Poco::format("failed shader: %s", string("")));
00118     }
00119 
00120     _small1 = _renderer.createRenderTarget(deviceW / 8, deviceH / 8, D3DFMT_A8R8G8B8);
00121     _renderer.colorFill(_small1, 0);
00122     _small2 = _renderer.createRenderTarget(deviceW / 8, deviceH / 8, D3DFMT_A8R8G8B8);
00123     _renderer.colorFill(_small2, 0);
00124     _diff = _renderer.createRenderTarget(deviceW / 8, deviceH / 8, D3DFMT_A8R8G8B8);
00125     _diff2 = _renderer.createLockableSurface(deviceW / 8, deviceH / 8, D3DFMT_A8R8G8B8);
00126     _photo = _renderer.createRenderTarget(deviceW, deviceH, D3DFMT_A8R8G8B8);
00127     _renderer.colorFill(_photo, 0);
00128 
00129     set("alpha", 1.0f);
00130     _duration = media->duration() * 60 / 1000;
00131     _current = 0;
00132     _mediaID = media->id();
00133     return true;
00134 }
00135 
00136 void CvContent::openDetectMovie() {
00137     _log.information("*openDetectMovie");
00138     SAFE_DELETE(_detectedItem);
00139     if (!_detectFiles.empty()) {
00140         vector<MediaItemFile> files;
00141         files.push_back(MediaItemFile(MediaTypeMovie, _detectFiles.at(rand() % _detectFiles.size()), ""));
00142         _detectedItem = new MediaItem(MediaTypeMovie, "detected", "detected", 0, false, files);
00143         if (_detectedMovie->open(_detectedItem)) {
00144     //      _detectedMovie->setPosition(conf->stageRect.left, conf->stageRect.top);
00145     //      _detectedMovie->setBounds(conf->stageRect.right, conf->stageRect.bottom);
00146     //  } else {
00147     //      SAFE_DELETE(_detectedMovie);
00148         }
00149     }
00150 }
00151 
00152 
00156 void CvContent::play() {
00157     _playing = true;
00158     _playTimer.start();
00159 }
00160 
00164 void CvContent::stop() {
00165     _playing = false;
00166 }
00167 
00168 bool CvContent::useFastStop() {
00169     return true;
00170 }
00171 
00175 const bool CvContent::playing() const {
00176     return _playing;
00177 }
00178 
00179 const bool CvContent::finished() {
00180     if (_duration > 0) {
00181         if (_detectedMovie && _detectedMovie->playing() && !_detectedMovie->finished()) {
00182             return false;
00183         }
00184         return _current >= _duration;
00185     }
00186     return false;
00187 }
00188 
00190 void CvContent::close() {
00191     stop();
00192     _mediaID.clear();
00193 
00194     Poco::DateTime now;
00195     now.makeLocal(Poco::Timezone::tzd());
00196     std::wstring wfile;
00197     Poco::UnicodeConverter::toUTF16(Poco::format("photos/snap%02d%02d%02d%02d.png", now.day(), now.hour(), now.minute(), now.second()), wfile);
00198     HRESULT hr = D3DXSaveTextureToFile(wfile.c_str(), D3DXIFF_PNG, _photo, NULL);
00199 
00200     {
00201         Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00202         SAFE_RELEASE(_fx);
00203         SAFE_RELEASE(_small1);
00204         SAFE_RELEASE(_small2);
00205         SAFE_RELEASE(_diff);
00206         SAFE_RELEASE(_diff2);
00207         SAFE_RELEASE(_photo);
00208         SAFE_DELETE(_normalMovie);
00209         SAFE_DELETE(_normalItem);
00210         SAFE_DELETE(_detectedMovie);
00211         SAFE_DELETE(_detectedItem);
00212     }
00213 }
00214 
00215 void CvContent::process(const DWORD& frame) {
00216     if (_playing) {
00217         if (_keycode != 0) {
00218             switch (_keycode) {
00219                 case 'P':
00220                     _clipY-=1;
00221                     break;
00222                 case VK_OEM_PERIOD:
00223                     _clipY+=1;
00224                     break;
00225                 case 'L':
00226                     _clipX-=1;
00227                     break;
00228                 case VK_OEM_PLUS:
00229                     _clipX+=1;
00230                     break;
00231 
00232                 case VK_OEM_4:
00233                     _clipH-=1;
00234                     break;
00235                 case VK_OEM_102:
00236                     _clipH+=1;
00237                     break;
00238                 case VK_OEM_1:
00239                     _clipW-=1;
00240                     break;
00241                 case VK_OEM_6:
00242                     _clipW+=1;
00243                     break;
00244 
00245                 case '8':
00246                     _detectThreshold--;
00247                     break;
00248                 case '9':
00249                     _detectThreshold++;
00250                     break;
00251 
00252                 case '0':
00253                     _intervalDiff--;
00254                     break;
00255                 case VK_OEM_MINUS:
00256                     _intervalDiff++;
00257                     break;
00258 
00259                 case VK_OEM_7:
00260                     _intervalSmall--;
00261                     break;
00262                 case VK_OEM_5:
00263                     _intervalSmall++;
00264                     break;
00265 
00266                 case 'S':
00267                     saveConfiguration();
00268                     _statusFrame = frame;
00269                     _status = "PARAMETER SAVED.";
00270                     break;
00271 
00272                 default:
00273                     _log.information(Poco::format("key: %?x", _keycode));
00274             }
00275         }
00276 
00277 //      if (get("prepare") != "true") {
00278 //      }
00279         if (_normalMovie) {
00280             _normalMovie->process(frame);
00281             if (_normalMovie->playing() && _normalMovie->finished()) {
00282                 _normalMovie->seek(0);
00283                 _normalMovie->play();
00284             }
00285         }
00286         if (_detectedMovie) {
00287             _detectedMovie->process(frame);
00288             if (!_detectedMovie->opened().empty() && !_detected && _diffCount > _detectThreshold) {
00289                 if (_viewPhoto == 0 || (frame - _viewPhoto) > 500) {
00290                     if (_detectCount > 0) {
00291                         if (_normalMovie) _normalMovie->stop();
00292                         _detectedMovie->play();
00293                         _detected = true;
00294                         _doShutter = frame;
00295                     } else {
00296                         // 検出回数上限
00297                         _current = _duration;
00298                     }
00299                 }
00300             }
00301             if (_detectedMovie->playing() && _detectedMovie->finished()) {
00302                 _detectedMovie->close();
00303 //              _detectedMovie->seek(0);
00304                 if (_normalMovie) _normalMovie->play();
00305                 _detectCount--;
00306                 if (_detectCount > 0) activeOpenDetectMovie();
00307                 _detected = false;
00308                 _viewPhoto = frame;
00309             }
00310         }
00311         _current++;
00312     }
00313 }
00314 
00315 void CvContent::draw(const DWORD& frame) {
00316     if (!_mediaID.empty() && _playing) {
00317         Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00318         LPDIRECT3DTEXTURE9 cameraImage = _scene->getCameraImage();
00319         DWORD col = 0xffffffff;
00320         _renderer.drawTexture(640, 0, 640, 480, cameraImage, 0, col, col, col, col);
00321         LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00322         if (_fx) {
00323             LPDIRECT3DSURFACE9 orgRT;
00324             HRESULT hr = device->GetRenderTarget(0, &orgRT);
00325 
00326             // 単純化
00327             col = 0xffffffff;
00328             D3DSURFACE_DESC desc;
00329             hr = _small1->GetLevelDesc(0, &desc);
00330             VERTEX dst[] =
00331             {
00332                 {F(0              - 0.5), F(0               - 0.5), 0.0f, 1.0f, col, 0, 0},
00333                 {F(0 + desc.Width - 0.5), F(0               - 0.5), 0.0f, 1.0f, col, 1, 0},
00334                 {F(0              - 0.5), F(0 + desc.Height - 0.5), 0.0f, 1.0f, col, 0, 1},
00335                 {F(0 + desc.Width - 0.5), F(0 + desc.Height - 0.5), 0.0f, 1.0f, col, 1, 1}
00336             };
00337             LPDIRECT3DSURFACE9 surface;
00338             if ((frame % _intervalDiff) == 0) {
00339                 _small1->GetSurfaceLevel(0, &surface);
00340                 hr = device->SetRenderTarget(0, surface);
00341                 _renderer.drawTexture(0, 0, desc.Width, desc.Height, _clipX, _clipY, _clipW, _clipH, cameraImage, 0, col, col, col, col);
00342                 SAFE_RELEASE(surface);
00343             }
00344             if ((frame % _intervalSmall) == 0) {
00345                 _small2->GetSurfaceLevel(0, &surface);
00346                 hr = device->SetRenderTarget(0, surface);
00347                 _renderer.drawTexture(0, 0, desc.Width, desc.Height, _clipX, _clipY, _clipW, _clipH, cameraImage, 0, col, col, col, col);
00348                 SAFE_RELEASE(surface);
00349 
00350                 // 差分
00351                 _diff->GetSurfaceLevel(0, &surface);
00352                 hr = device->SetRenderTarget(0, surface);
00353                 _fx->SetTechnique("BasicTech");
00354                 _fx->SetFloat("subtract", _subtract);
00355                 _fx->SetTexture("bgTex", _small1);
00356                 _fx->SetTexture("currentTex", _small2);
00357                 hr = _fx->Begin(0, 0);
00358                 if (SUCCEEDED(hr)) {
00359                     _fx->BeginPass(1);
00360                     device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, dst, VERTEX_SIZE);
00361                     _fx->EndPass();
00362                     _fx->End();
00363                 }
00364                 SAFE_RELEASE(surface);
00365                 if (_renderer.getRenderTargetData(_diff, _diff2)) {
00366                     D3DSURFACE_DESC desc;
00367                     _diff2->GetDesc(&desc);
00368                     D3DLOCKED_RECT lockedRect;
00369                     hr = _diff2->LockRect(&lockedRect, NULL, 0);
00370                     if (SUCCEEDED(hr)) {
00371                         _diffCount = 0;
00372                         DWORD* buf = (DWORD*)lockedRect.pBits;
00373                         for (int i = 0; i < lockedRect.Pitch / 4 * desc.Height; i++) {
00374                             if (buf[i] == 0xffffffff) _diffCount++;
00375                         }
00376                         _diff2->UnlockRect();
00377                         if (desc.Width * desc.Height <= _diffCount) _diffCount = 0;
00378                     }
00379                 }
00380             }
00381             hr = device->SetRenderTarget(0, orgRT);
00382             SAFE_RELEASE(orgRT);
00383         }
00384 
00385         if (_doShutter > 0 && (frame - _doShutter) > 60) {
00386             LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00387             LPDIRECT3DSURFACE9 orgRT;
00388             HRESULT hr = device->GetRenderTarget(0, &orgRT);
00389 
00390             D3DSURFACE_DESC desc;
00391             hr = _photo->GetLevelDesc(0, &desc);
00392             LPDIRECT3DSURFACE9 surface;
00393             _photo->GetSurfaceLevel(0, &surface);
00394             hr = device->SetRenderTarget(0, surface);
00395             DWORD col = 0xffffffff;
00396             _renderer.drawTexture(0, 0, desc.Width, desc.Height, cameraImage, 0, col, col, col, col);
00397             SAFE_RELEASE(surface);
00398 
00399             hr = device->SetRenderTarget(0, orgRT);
00400             SAFE_RELEASE(orgRT);
00401             _doShutter = 0;
00402         }
00403 
00404         if (_detected) {
00405             if (_detectedMovie) _detectedMovie->draw(frame);
00406         } else {
00407             if (_normalMovie) _normalMovie->draw(frame);
00408         }
00409 
00410         int x = config().stageRect.left;
00411         int y = config().stageRect.top;
00412         int w = config().stageRect.right;
00413         int h = config().stageRect.bottom;
00414         if (_viewPhoto > 0 && (frame - _viewPhoto) > 100 && (frame - _viewPhoto) < 500) {
00415             float alpha = 1.0f;
00416             if ((frame - _viewPhoto) > 400) {
00417                 alpha = F(500 - (frame - _viewPhoto)) / 100;
00418             }
00419             DWORD col = ((DWORD)(0x66 * alpha) << 24) | 0x000000;
00420             _renderer.drawTexture(x + 60, y + 20, w - 80, h - 20, NULL, 0, col, col, col, col);
00421             col = ((DWORD)(0xff * alpha) << 24) | 0xffffff;
00422             _renderer.drawTexture(x + 40, y + 10, w - 80, h - 20, NULL, 0, col, col, col, col);
00423             _renderer.drawTexture(x + 43, y + 13, w - 86, h - 26, _photo, 0, col, col, col, col);
00424         }
00425 
00426         // ステータス表示
00427         col = 0x66669966;
00428         _renderer.drawTexture(640 + _clipX, _clipY, _clipW, _clipH, NULL, 0, col, col, col, col);
00429         _renderer.drawFontTextureText(640 + _clipX, _clipY, 8, 10, 0xccffffff, Poco::format("(%d,%d)-%dx%d", _clipX, _clipY, _clipW, _clipH));
00430         col = 0xffffffff;
00431         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00432         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00433         _renderer.drawTexture(320, 480, 320, 240, _diff, 0, col, col, col, col);
00434         _renderer.drawFontTextureText(320, 480, 12, 16, 0xccffffff, Poco::format("<%04d/%04d>", _diffCount, _detectThreshold));
00435         _renderer.drawTexture(640, 480, 320, 240, _small1, 0, col, col, col, col);
00436         float interval = _intervalDiff / 60.0f;
00437         _renderer.drawFontTextureText(640, 480, 12, 16, 0xccffffff, Poco::format("%d(%0.2hfs)", _intervalDiff, interval));
00438         _renderer.drawTexture(960, 480, 320, 240, _small2, 0, col, col, col, col);
00439         interval = _intervalSmall / 60.0f;
00440         _renderer.drawFontTextureText(960, 480, 12, 16, 0xccffffff, Poco::format("%d(%0.2hfs)", _intervalSmall, interval));
00441         _renderer.drawTexture(0, 480, 320, 240, _photo, 0, col, col, col, col);
00442         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00443         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00444         if (_statusFrame > 0 && (frame - _statusFrame) < 200) {
00445             _renderer.drawFontTextureText(640, config().mainRect.bottom - 32, 24, 32, 0xccff3333, _status);
00446         }
00447     }
00448 }
00449 
00450 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines