svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/CaptureContent.cpp
Go to the documentation of this file.
00001 #include <Poco/DateTime.h>
00002 #include <Poco/Timezone.h>
00003 #include <Poco/Mutex.h>
00004 #include <Poco/Thread.h>
00005 #include <Poco/Runnable.h>
00006 #include <Poco/Util/XMLConfiguration.h>
00007 #include <Poco/UnicodeConverter.h>
00008 
00009 #include "CaptureContent.h"
00010 
00011 using Poco::Util::XMLConfiguration;
00012 
00013 CaptureContent::CaptureContent(Renderer& renderer, int splitType): Content(renderer, splitType), 
00014     _scene(NULL), _fx(NULL), _small1(NULL), _small2(NULL), _diff(NULL), _diff2(NULL), _image(NULL),
00015     _detected(false), _doShutter(0), _viewPhoto(0), _finished(true), _playing(false), _statusFrame(0)
00016 {
00017     initialize();
00018     _scene = (CaptureScenePtr)_renderer.getScene("capture");
00019 }
00020 
00021 CaptureContent::‾CaptureContent() {
00022     initialize();
00023 }
00024 
00025 void CaptureContent::saveConfiguration() {
00027     try {
00028         Poco::Util::XMLConfiguration* xml = new Poco::Util::XMLConfiguration("cvcap-config.xml");
00029         if (xml) {
00030             xml->setInt("detect", _detectThreshold);
00031             xml->setInt("intervals[@diff]", _intervalDiff);
00032             xml->setInt("intervals[@small]", _intervalSmall);
00033 //          xml->setInt("clip[@x]", _clipX);
00034 //          xml->setInt("clip[@y]", _clipY);
00035 //          xml->setInt("clip[@w]", _clipW);
00036 //          xml->setInt("clip[@h]", _clipH);
00037             xml->save("cv-config.xml");
00038             xml->release();
00039             _log.information("cv parameters saved");
00040         }
00041     } catch (Poco::Exception& ex) {
00042         _log.warning(ex.displayText());
00043     }
00044 }
00045 
00046 void CaptureContent::initialize() {
00047     close();
00048 }
00049 
00050 bool CaptureContent::open(const MediaItemPtr media, const int offset) {
00051     initialize();
00052 
00054     int deviceW = 0;
00055     int deviceH = 0;
00056     try {
00057         XMLConfiguration* xml = new XMLConfiguration("cvcap-config.xml");
00058 //      _deviceNo = xml->getInt("device[@no]", 0);
00059         deviceW = xml->getInt("device[@w]", 640);
00060         deviceH = xml->getInt("device[@h]", 480);
00061 //      _deviceFPS = xml->getInt("device[@fps]", 60);
00062         _subtract = xml->getDouble("subtract", 0.5);
00063 //      _samples = xml->getInt("samples", 4);
00064         _detectThreshold = xml->getInt("detect", 50);
00065         _intervalDiff = xml->getInt("intervals[@diff]", 60);
00066         _intervalSmall = xml->getInt("intervals[@small]", 12);
00067         string file = xml->getString("image", "");
00068         if (!file.empty()) {
00069             _image = _renderer.createTexture(file);
00070         }
00071 //      _clipX = xml->getInt("clip[@x]", 0);
00072 //      _clipY = xml->getInt("clip[@y]", 0);
00073 //      _clipW = xml->getInt("clip[@w]", deviceW);
00074 //      _clipH = xml->getInt("clip[@h]", deviceH);
00075         xml->release();
00076     } catch (Poco::Exception& ex) {
00077         _log.warning(ex.displayText());
00078     }
00079 
00081     std::wstring wfile;
00082     Poco::UnicodeConverter::toUTF16(string("subbg.fx"), wfile);
00083     LPD3DXBUFFER errors = NULL;
00084     HRESULT hr = D3DXCreateEffectFromFile(_renderer.get3DDevice(), wfile.c_str(), 0, 0, D3DXSHADER_DEBUG, 0, &_fx, &errors);
00085     if (errors) {
00086         std::vector<char> text(errors->GetBufferSize());
00087         memcpy(&text[0], errors->GetBufferPointer(), errors->GetBufferSize());
00088         text.push_back('¥0');
00089         _log.warning(Poco::format("shader compile error: %s", string(&text[0])));
00090         SAFE_RELEASE(errors);
00091     } else if (FAILED(hr)) {
00092         _log.warning(Poco::format("failed shader: %s", string("")));
00093     }
00094 
00096     _small1 = _renderer.createRenderTarget(32, 32, D3DFMT_A8R8G8B8);
00097     _renderer.colorFill(_small1, 0);
00098     _small2 = _renderer.createRenderTarget(32, 32, D3DFMT_A8R8G8B8);
00099     _renderer.colorFill(_small2, 0);
00100     _diff = _renderer.createRenderTarget(32, 32, D3DFMT_A8R8G8B8);
00101     _diff2 = _renderer.createLockableSurface(32, 32, D3DFMT_A8R8G8B8);
00102 
00103     set("alpha", 1.0f);
00104     _duration = media->duration() * 60 / 1000;
00105     _current = 0;
00106     _mediaID = media->id();
00107     return true;
00108 }
00109 
00110 
00111 void CaptureContent::play() {
00112     _playing = true;
00113     _playTimer.start();
00114 }
00115 
00116 void CaptureContent::stop() {
00117     _playing = false;
00118 }
00119 
00120 bool CaptureContent::useFastStop() {
00121     return true;
00122 }
00123 
00124 const bool CaptureContent::playing() const {
00125     return _playing;
00126 }
00127 
00128 const bool CaptureContent::finished() {
00129     return _current >= _duration;
00130 }
00131 
00132 void CaptureContent::close() {
00133     stop();
00134     _mediaID.clear();
00135 
00136     {
00137         Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00138         SAFE_RELEASE(_fx);
00139         SAFE_RELEASE(_small1);
00140         SAFE_RELEASE(_small2);
00141         SAFE_RELEASE(_diff);
00142         SAFE_RELEASE(_diff2);
00143         SAFE_RELEASE(_image);
00144     }
00145 }
00146 
00147 void CaptureContent::process(const DWORD& frame) {
00148     if (_playing) {
00149         if (_keycode != 0) {
00150             switch (_keycode) {
00151                 case '8':
00152                     _detectThreshold--;
00153                     break;
00154                 case '9':
00155                     _detectThreshold++;
00156                     break;
00157 
00158                 case '0':
00159                     _intervalDiff--;
00160                     break;
00161                 case VK_OEM_MINUS:
00162                     _intervalDiff++;
00163                     break;
00164 
00165                 case VK_OEM_7:
00166                     _intervalSmall--;
00167                     break;
00168                 case VK_OEM_5:
00169                     _intervalSmall++;
00170                     break;
00171 
00172                 case 'S':
00173                     saveConfiguration();
00174                     _statusFrame = frame;
00175                     _status = "PARAMETER SAVED.";
00176                     break;
00177 
00178                 default:
00179                     _log.information(Poco::format("key: %?x", _keycode));
00180             }
00181         }
00182 
00183         _current++;
00184     }
00185 }
00186 
00187 void CaptureContent::draw(const DWORD& frame) {
00188     if (!_mediaID.empty() && _playing) {
00189         Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00190         int x = config().stageRect.left;
00191         int y = config().stageRect.top;
00192         int w = config().stageRect.right;
00193         int h = config().stageRect.bottom;
00194 
00195         LPDIRECT3DTEXTURE9 cameraImage = _scene->getCameraImage();
00196         if (!cameraImage) return;
00197 
00198         DWORD col = 0xffffffff;
00199         _renderer.drawTexture(x, y, w, h, cameraImage, 0, col, col, col, col);
00200         if (_image) _renderer.drawTexture(x, y, _image, 0, col, col, col, col);
00201         LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00202         if (_fx) {
00203             LPDIRECT3DSURFACE9 orgRT;
00204             HRESULT hr = device->GetRenderTarget(0, &orgRT);
00205 
00206             // 単純化
00207             col = 0xffffffff;
00208             D3DSURFACE_DESC desc;
00209             hr = _small1->GetLevelDesc(0, &desc);
00210             VERTEX dst[] =
00211             {
00212                 {F(0              - 0.5), F(0               - 0.5), 0.0f, 1.0f, col, 0, 0},
00213                 {F(0 + desc.Width - 0.5), F(0               - 0.5), 0.0f, 1.0f, col, 1, 0},
00214                 {F(0              - 0.5), F(0 + desc.Height - 0.5), 0.0f, 1.0f, col, 0, 1},
00215                 {F(0 + desc.Width - 0.5), F(0 + desc.Height - 0.5), 0.0f, 1.0f, col, 1, 1}
00216             };
00217             LPDIRECT3DSURFACE9 surface;
00218             if ((frame % _intervalDiff) == 0) {
00219                 _small1->GetSurfaceLevel(0, &surface);
00220                 hr = device->SetRenderTarget(0, surface);
00221                 _renderer.drawTexture(0, 0, desc.Width, desc.Height, cameraImage, 0, col, col, col, col);
00222                 SAFE_RELEASE(surface);
00223             }
00224             if ((frame % _intervalSmall) == 0) {
00225                 _small2->GetSurfaceLevel(0, &surface);
00226                 hr = device->SetRenderTarget(0, surface);
00227                 _renderer.drawTexture(0, 0, desc.Width, desc.Height, cameraImage, 0, col, col, col, col);
00228                 SAFE_RELEASE(surface);
00229 
00230                 // 差分
00231                 _diff->GetSurfaceLevel(0, &surface);
00232                 hr = device->SetRenderTarget(0, surface);
00233                 _fx->SetTechnique("BasicTech");
00234                 _fx->SetFloat("subtract", _subtract);
00235                 _fx->SetTexture("bgTex", _small1);
00236                 _fx->SetTexture("currentTex", _small2);
00237                 hr = _fx->Begin(0, 0);
00238                 if (SUCCEEDED(hr)) {
00239                     _fx->BeginPass(1);
00240                     device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, dst, VERTEX_SIZE);
00241                     _fx->EndPass();
00242                     _fx->End();
00243                 }
00244                 SAFE_RELEASE(surface);
00245 
00246                 if (_renderer.getRenderTargetData(_diff, _diff2)) {
00247                     D3DSURFACE_DESC desc;
00248                     _diff2->GetDesc(&desc);
00249                     D3DLOCKED_RECT lockedRect;
00250                     hr = _diff2->LockRect(&lockedRect, NULL, 0);
00251                     if (SUCCEEDED(hr)) {
00252                         _diffCount = 0;
00253                         DWORD* buf = (DWORD*)lockedRect.pBits;
00254                         int pitch = lockedRect.Pitch / 4;
00255                         DWORD p, p0, p1, p2, p3;
00256                         for (int i = 0; i < 2; i++) {
00257                             for (int y = 0; y < desc.Height; y++) {
00258                                 for (int x = 0; x < pitch; x++) {
00259                                     p0 = 0; p1 = 0; p2 = 0; p3 = 0;
00260                                     if (y > 0) p0 = buf[(y - 1) * pitch + x];
00261                                     if (y < desc.Height - 1) p3 = buf[(y + 1) * pitch + x];
00262                                     if (x > 0) p1 = buf[y * pitch + x - 1];
00263                                     if (x < pitch - 1) p2 = buf[y * pitch + x + 1];
00264                                     p = buf[y * pitch + x];
00265                                     if (p == 0xff000000 && p1 == p2 && p2 == 0xffffffff) buf[y * pitch + x] = 0xffffffff;
00266                                     if (p == 0xff000000 && p0 == p3 && p3 == 0xffffffff) buf[y * pitch + x] = 0xffffffff;
00267                                     if (p == 0xffffffff && p0 == p1 && p1 == p2 && p2 == p3 && p3 == 0xff000000) buf[y * pitch + x] = 0xff000000;
00268                                 }
00269                             }
00270                         }
00271 
00272                         for (int i = 0; i < pitch * desc.Height; i++) {
00273                             if (buf[i] == 0xffffffff) _diffCount++;
00274                         }
00275                         _diff2->UnlockRect();
00276                         if (!_renderer.updateRenderTargetData(_diff, _diff2)) {
00277                             _log.warning("failed updateRenderTargetData");
00278                         }
00279                         if (desc.Width * desc.Height <= _diffCount) _diffCount = 0;
00280                     }
00281                 }
00282             }
00283             hr = device->SetRenderTarget(0, orgRT);
00284             SAFE_RELEASE(orgRT);
00285         }
00286 
00287         // ステータス表示
00288         col = 0xffffffff;
00289         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00290         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00291         _renderer.drawTexture(320, 480, 320, 240, _diff, 0, col, col, col, col);
00292         _renderer.drawFontTextureText(320, 480, 12, 16, 0xccffffff, Poco::format("<%04d/%04d>", _diffCount, _detectThreshold));
00293         _renderer.drawTexture(640, 480, 320, 240, _small1, 0, col, col, col, col);
00294         float interval = _intervalDiff / 60.0f;
00295         _renderer.drawFontTextureText(640, 480, 12, 16, 0xccffffff, Poco::format("%d(%0.2hfs)", _intervalDiff, interval));
00296         _renderer.drawTexture(960, 480, 320, 240, _small2, 0, col, col, col, col);
00297         interval = _intervalSmall / 60.0f;
00298         _renderer.drawFontTextureText(960, 480, 12, 16, 0xccffffff, Poco::format("%d(%0.2hfs)", _intervalSmall, interval));
00299         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00300         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00301         if (_statusFrame > 0 && (frame - _statusFrame) < 200) {
00302             _renderer.drawFontTextureText(640, config().mainRect.bottom - 32, 24, 32, 0xccff3333, _status);
00303         }
00304     }
00305 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines