svvitch
digital signage player
|
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 }