svvitch
digital signage player
|
00001 #include "ImageContent.h" 00002 00003 00004 ImageContent::ImageContent(Renderer& renderer, int splitType, float x, float y, float w, float h): 00005 Content(renderer, splitType, x, y, w, h), _target(NULL), _finished(true), _playing(false) 00006 { 00007 initialize(); 00008 } 00009 00010 ImageContent::‾ImageContent() { 00011 // _log.information("Image::‾Image()"); 00012 initialize(); 00013 } 00014 00015 00016 void ImageContent::initialize() { 00017 // _log.information("Image::initialize()"); 00018 close(); 00019 } 00020 00021 bool ImageContent::open(const MediaItemPtr media, const int offset) { 00022 initialize(); 00023 00024 _iw = 0; 00025 _ih = 0; 00026 _dy = 0; 00027 vector<LPDIRECT3DTEXTURE9> textures; 00028 bool valid = true; 00029 D3DFORMAT fomart = D3DFMT_X8R8G8B8; // D3DFMT_A8R8G8B8; 00030 LPDIRECT3DDEVICE9 device = _renderer.get3DDevice(); 00031 int i = 0; 00032 for (vector<MediaItemFile>::const_iterator it = media->files().begin(); it != media->files().end(); it++) { 00033 if (i < offset) { 00034 i++; 00035 continue; 00036 } 00037 00038 MediaItemFile mif = *it; 00039 if (mif.type() == MediaTypeImage) { 00040 LPDIRECT3DTEXTURE9 texture = _renderer.createTexture(mif.file()); 00041 if (texture) { 00042 D3DSURFACE_DESC desc; 00043 HRESULT hr = texture->GetLevelDesc(0, &desc); 00044 if (config().splitType != 0 && config().splitSize.cy < desc.Height) { 00045 // テクスチャ分割 00046 _ih = config().splitSize.cy; 00047 LPDIRECT3DSURFACE9 src = NULL; 00048 hr = texture->GetSurfaceLevel(0, &src); 00049 for (int y = 0; y < desc.Height; y += _ih) { 00050 LPDIRECT3DTEXTURE9 t = _renderer.createRenderTarget(desc.Width, _ih, fomart); 00051 LPDIRECT3DSURFACE9 dst = NULL; 00052 hr = t->GetSurfaceLevel(0, &dst); 00053 RECT srcRect = {0, y, desc.Width, y + _ih}; 00054 hr = device->StretchRect(src, &srcRect, dst, NULL, D3DTEXF_NONE); 00055 if SUCCEEDED(hr) { 00056 _iw += desc.Width; 00057 textures.push_back(t); 00058 // _log.information(Poco::format("texture divid: %02d-%02d", y, (y + _ih - 1))); 00059 if (_iw > config().stageRect.right) break; 00060 } 00061 SAFE_RELEASE(dst); 00062 } 00063 SAFE_RELEASE(src); 00064 SAFE_RELEASE(texture); 00065 00066 } else { 00067 _iw += desc.Width; 00068 if (_ih < desc.Height) _ih = desc.Height; 00069 textures.push_back(texture); 00070 if (_iw > config().stageRect.right) break; 00071 } 00072 // _log.information(Poco::format("opened texture: %s", mif.file())); 00073 } else { 00074 _log.warning(Poco::format("failed open: %s", mif.file())); 00075 valid = false; 00076 } 00077 } else { 00078 // MediaTypeMixの場合はファイル単位で処理するので繰り返さない 00079 if (media->type() == MediaTypeMix) break; 00080 } 00081 } 00082 if (!valid) return false; 00083 // _tw = 1024; 00084 _tw = _iw > config().imageSplitWidth?config().imageSplitWidth:_iw; 00085 _th = _tw != _iw?_ih * L(ceil(F(_iw) / _tw)):_ih; 00086 _target = _renderer.createRenderTarget(_tw, _th, fomart); 00087 if (_target) { 00088 _renderer.colorFill(_target, 0xff000000); 00089 LPDIRECT3DSURFACE9 dst = NULL; 00090 HRESULT hr = _target->GetSurfaceLevel(0, &dst); 00091 if (SUCCEEDED(hr)) { 00092 int dx = 0, dy = 0; 00093 for (vector<LPDIRECT3DTEXTURE9>::iterator it = textures.begin(); it != textures.end(); it++) { 00094 LPDIRECT3DTEXTURE9 texture = *it; 00095 D3DSURFACE_DESC desc; 00096 hr = texture->GetLevelDesc(0, &desc); 00097 int sx = 0, tw = desc.Width, th = desc.Height; 00098 while (sx < tw) { 00099 int w = (tw - sx < _tw - dx)?tw - sx:_tw - dx; 00100 00101 LPDIRECT3DSURFACE9 src = NULL; 00102 hr = texture->GetSurfaceLevel(0, &src); 00103 RECT srcRect = {sx, 0, sx + w, th}; 00104 RECT dstRect = {dx, dy, dx + w, dy + th}; 00105 hr = device->StretchRect(src, &srcRect, dst, &dstRect, D3DTEXF_NONE); 00106 SAFE_RELEASE(src); 00107 dx += w; 00108 sx += w; 00109 if (dx >= _tw) { 00110 dx = 0; 00111 dy += th; 00112 } 00113 } 00114 SAFE_RELEASE(texture); 00115 } 00116 SAFE_RELEASE(dst); 00117 } else { 00118 _log.warning("failed get surface"); 00119 valid = false; 00120 } 00121 } else { 00122 _log.warning("failed GetSurface()"); 00123 valid = false; 00124 } 00125 00126 if (valid) { 00127 _log.information(Poco::format("tiled texture size: %dx%d (native:%dx%d)", _iw, _ih, _tw, _th)); 00128 _mediaID = media->id(); 00129 _duration = media->duration() * 60 / 1000; 00130 _current = 0; 00131 set("alpha", 1.0f); 00132 _finished = false; 00133 return true; 00134 } 00135 00136 return false; 00137 } 00138 00139 00140 void ImageContent::play() { 00141 _playing = true; 00142 _playTimer.start(); 00143 } 00144 00145 void ImageContent::stop() { 00146 _playing = false; 00147 } 00148 00149 const bool ImageContent::playing() const { 00150 return _playing; 00151 } 00152 00153 const bool ImageContent::finished() { 00154 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00155 return _current >= _duration; 00156 } 00157 00158 void ImageContent::close() { 00159 stop(); 00160 _mediaID.clear(); 00161 _current = 0; 00162 { 00163 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00164 SAFE_RELEASE(_target); 00165 _tw = 0; 00166 _th = 0; 00167 } 00168 } 00169 00170 void ImageContent::process(const DWORD& frame) { 00171 if (_playing) { 00172 _current++; 00173 if (_duration < _current) _current = _duration; 00174 00175 int fps = 60; 00176 unsigned long cu = _current / fps; 00177 unsigned long re = (_duration - _current) / fps; 00178 string t1 = Poco::format("%02lu:%02lu:%02lu.%02d", cu / 3600, cu / 60, cu % 60, (_current % fps) / 2); 00179 string t2 = Poco::format("%02lu:%02lu:%02lu.%02d", re / 3600, re / 60, re % 60, ((_duration - _current) % fps) / 2); 00180 set("time", Poco::format("%s %s", t1, t2)); 00181 set("time_current", t1); 00182 set("time_remain", t2); 00183 } 00184 } 00185 00186 void ImageContent::draw(const DWORD& frame) { 00187 if (!_mediaID.empty() && _playing) { 00188 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00189 LPDIRECT3DDEVICE9 device = _renderer.get3DDevice(); 00190 // _dy -= 0.5f; 00191 // if (_dy <= -32) _dy = 32; 00192 float alpha = getF("alpha", 1.0f); 00193 DWORD col = ((DWORD)(0xff * alpha) << 24) | 0xffffff; 00194 const int cw = config().splitSize.cx; 00195 const int ch = config().splitSize.cy; 00196 switch (_splitType) { 00197 case 1: 00198 { 00199 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 00200 RECT scissorRect; 00201 device->GetScissorRect(&scissorRect); 00202 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 00203 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 00204 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 00205 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 00206 float x = _x; 00207 float y = _y; 00208 int ix = 0, sx = 0, sy = 0, dx = (int)x / (cw * config().splitCycles) * cw, dxx = (int)fmod(x, cw), dy = ch * ((int)x / cw) % (config().splitCycles * ch); 00209 int cww = 0; 00210 int chh = (ch > _ih)?_ih:ch; 00211 RECT rect = {dx, dy, dx + cw, dy + ch}; 00212 device->SetScissorRect(&rect); 00213 while (dx < config().mainRect.right) { 00214 int cx = dx * config().splitCycles + dy / ch * cw; // cx=実際の映像の横位置 00215 if (cx + dxx >= config().stageRect.right) break; 00216 if (cw - dxx >= _tw - sx) { 00217 // src横が足りない場合 00218 cww = _tw - sx; 00219 //_log.information(Poco::format("src: %d %d %d", cx, dxx, cww)); 00220 _renderer.drawTexture(dx + dxx, y + dy, cww, chh, sx, sy, cww, chh, _target, 0, col, col, col, col); 00221 dxx += cww; 00222 sx = 0; 00223 if (sy + ch < _th) { 00224 // src折返し 00225 sy += ch; 00226 if (_th - sy < ch) { 00227 chh = _th - sy; 00228 } 00229 } else { 00230 // src繰返し 00231 sy = 0; 00232 ix = 0; 00233 } 00234 if (dxx < cw) continue; 00235 } else { 00236 // src横が残る場合 00237 if (_iw - ix < (cw - dxx)) { 00238 cww = _iw - ix; 00239 } else { 00240 cww = cw - dxx; 00241 } 00242 //_log.information(Poco::format("dst: %d %d %d", cx, dxx, cww)); 00243 _renderer.drawTexture(dx + dxx, y + dy, cww, chh, sx, sy, cww, chh, _target,0, col, col, col, col); 00244 sx += cww; 00245 ix += cww; 00246 } 00247 if (ix >= _iw) { 00248 ix = 0; 00249 sx = 0; 00250 sy = 0; 00251 chh = (ch > _ih)?_ih:ch; 00252 } 00253 dy += ch; 00254 if (dy >= config().splitCycles * ch) { 00255 dx += cw; 00256 dy = 0; 00257 } 00258 dxx = 0; 00259 ::SetRect(&rect, dx, dy, dx + cw, dy + ch); 00260 device->SetScissorRect(&rect); 00261 } 00262 // _log.information("image check"); 00263 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 00264 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 00265 device->SetScissorRect(&scissorRect); 00266 } 00267 break; 00268 00269 case 2: 00270 { 00271 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 00272 RECT scissorRect; 00273 device->GetScissorRect(&scissorRect); 00274 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 00275 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 00276 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 00277 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 00278 int cww = cw; 00279 int chh = ch; 00280 int sw = _tw / cw; 00281 if (sw <= 0) { 00282 sw = 1; 00283 cww = _tw; 00284 } 00285 int sh = _th / ch; 00286 if (sh <= 0) { 00287 sh = 1; 00288 chh = _th; 00289 } 00290 for (int sy = 0; sy < sh; sy++) { 00291 int ox = (sy % 2) * cw * 8 + config().stageRect.left; 00292 int oy = (sy / 2) * ch * 4 + config().stageRect.top; 00293 for (int sx = 0; sx < sw; sx++) { 00294 int dx = (sx / 4) * cw; 00295 int dy = ch * 3 - (sx % 4) * ch; 00296 RECT rect = {ox + dx, oy + dy, ox + dx + cw, oy + dy + ch}; 00297 device->SetScissorRect(&rect); 00298 _renderer.drawTexture(ox + dx + _x, oy + dy + _y, cww, chh, sx * cw, sy * ch, cww, chh, _target, 0, col, col, col, col); 00299 } 00300 } 00301 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 00302 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 00303 device->SetScissorRect(&scissorRect); 00304 } 00305 break; 00306 00307 default: 00308 { 00309 RECT rect = config().stageRect; 00310 string aspectMode = get("aspect-mode"); 00311 if (aspectMode == "fit") { 00312 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 00313 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 00314 _renderer.drawTexture(L(_x), L(_y), L(_w), L(_h), _target, 0, col, col, col, col); 00315 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 00316 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 00317 00318 } else if (aspectMode == "lefttop") { 00319 _renderer.drawTexture(L(_x), L(_y), _target, 0, col, col, col, col); 00320 00321 } else if (aspectMode == "center") { 00322 int x = _x + (_iw - _w) / 2; 00323 int y = _y + (_ih - _h) / 2; 00324 _renderer.drawTexture(x, y, _target, 0, col, col, col, col); 00325 00326 } else { 00327 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 00328 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 00329 if (alpha > 0.0f) { 00330 DWORD base = ((DWORD)(0xff * alpha) << 24) | 0x000000; 00331 _renderer.drawTexture(_x, _y, _w, _h, NULL, 0, base, base, base, base); 00332 float dar = F(_w) / _h; 00333 if (_h * dar > _w) { 00334 // 画角よりディスプレイサイズは横長 00335 long h = _w / dar; 00336 long dy = (_h - h) / 2; 00337 _renderer.drawTexture(L(_x), L(_y + dy), L(_w), h, _target, 0, col, col, col, col); 00338 } else { 00339 long w = _h * dar; 00340 long dx = (_w - w) / 2; 00341 _renderer.drawTexture(L(_x + dx), L(_y), w, L(_h), _target, 0, col, col, col, col); 00342 } 00343 } 00344 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 00345 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 00346 } 00347 } 00348 00349 } 00350 } else { 00351 if (get("prepare") == "true") { 00352 int sy = getF("itemNo") * 20; 00353 DWORD col = 0xccffffff; 00354 _renderer.drawTexture(700, 600 + sy, 324, 20, _target, 0, col, col, col, col); 00355 } 00356 } 00357 }