svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/ImageContent.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines