svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/VideoFrame.h
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #include <Poco/Logger.h>
00004 #include <Poco/Mutex.h>
00005 #include <Poco/Thread.h>
00006 #include <Poco/Runnable.h>
00007 #include <Poco/format.h>
00008 
00009 #include "FFBaseDecoder.h"
00010 #include "PerformanceTimer.h"
00011 
00012 //#ifndef _DEBUG
00013 //#include <omp.h>
00014 //#endif
00015 
00016 using std::queue;
00017 
00018 
00023 class VideoFrame
00024 {
00025 friend class FFVideoDecoder;
00026 private:
00027     Poco::Logger& _log;
00028 
00029     Renderer& _renderer;
00030     int _frameNumber;
00031     int _ow;
00032     int _oh;
00033     int _w[3];
00034     int _h[3];
00035     LPDIRECT3DTEXTURE9 _texture[3];
00036     LPD3DXEFFECT _fx;
00037 
00038     const Float toTexelU(const int pixel) {
00039         return F(pixel) / F(_ow);
00040     }
00041 
00042     const Float toTexelV(const int pixel) {
00043         return F(pixel) / F(_oh);
00044     }
00045 
00046 
00047 public:
00048     VideoFrame(Renderer& renderer): _log(Poco::Logger::get("")), _renderer(renderer) {
00049         _texture[0] = NULL;
00050         _texture[1] = NULL;
00051         _texture[2] = NULL;
00052         _fx = NULL;
00053     }
00054 
00055     VideoFrame(Renderer& renderer, const int w, const int h, const int linesize[], const D3DFORMAT format): _log(Poco::Logger::get("")), _renderer(renderer) {
00056         _ow = abs(linesize[0]) / 4;
00057         _oh = h;
00058         _w[0] = w;
00059         _h[0] = h;
00060         _texture[0] = renderer.createTexture(_ow, _oh, format);
00061         _texture[1] = NULL;
00062         _texture[2] = NULL;
00063         _fx = NULL;
00064     }
00065 
00066     VideoFrame(Renderer& renderer, const int w, const int h, const int linesize[], const int h2, const D3DFORMAT format, const LPD3DXEFFECT fx):
00067         _log(Poco::Logger::get("")), _renderer(renderer), _fx(fx)
00068     {
00069         _ow = linesize[0];
00070         _oh = h;
00071         _w[0] = w;
00072         _h[0] = h;
00073         _w[1] = w / 2;
00074         _h[1] = h2;
00075         _w[2] = w / 2;
00076         _h[2] = h2;
00077         for (int i = 0; i < 3; i++) {
00078             _texture[i] = renderer.createTexture(linesize[i], _h[i], format);
00079             // _log.information(Poco::format("texture: <%d>%dx%d", i, linesize[i], _h[i]));
00080         }
00081     }
00082 
00083     virtual ‾VideoFrame() {
00084         SAFE_RELEASE(_texture[0]);
00085         SAFE_RELEASE(_texture[1]);
00086         SAFE_RELEASE(_texture[2]);
00087     }
00088 
00089     const int frameNumber() const {
00090         return _frameNumber;
00091     }
00092 
00093     const int width() const {
00094         return _w[0];
00095     }
00096 
00097     const int height() const {
00098         return _h[0];
00099     }
00100 
00101     const bool equals(const int w, const int h, const D3DFORMAT format) {
00102         if (_texture[0]) {
00103             D3DSURFACE_DESC desc;
00104             HRESULT hr = _texture[0]->GetLevelDesc(0, &desc);
00105             if (SUCCEEDED(hr) && desc.Format == format && _ow == w && _oh == h) return true;
00106         }
00107         return false;
00108     }
00109 
00110     void copy(VideoFrame* frame) {
00111         _ow = frame->_ow;
00112         _oh = frame->_oh;
00113         _fx = frame->_fx;
00114         for (int i = 0; i < 3; i++) {
00115             _w[i] = frame->_w[i];
00116             _h[i] = frame->_h[i];
00117             if (frame->_texture[i]) {
00118                 D3DSURFACE_DESC desc;
00119                 HRESULT hr = frame->_texture[i]->GetLevelDesc(0, &desc);
00120                 if SUCCEEDED(hr) {
00121                     SAFE_RELEASE(_texture[i]);
00122                     _texture[i] = _renderer.createTexture(desc.Width, desc.Height, desc.Format);
00123                     _renderer.copyTexture(frame->_texture[i], _texture[i]);
00124                 }
00125             } else {
00126                 SAFE_RELEASE(_texture[i]);
00127             }
00128         }
00129     }
00130 
00131     void write(const AVFrame* frame) {
00132         if (_texture[1]) {
00133             // プレナー
00134             D3DLOCKED_RECT lockRect = {0};
00135             int i;
00136             //#ifndef _DEBUG
00137             //#pragma omp for private(i)
00138             //#endif
00139             for (i = 0; i < 3; i++) {
00140                 if (_texture[i]) {
00141                     HRESULT hr = _texture[i]->LockRect(0, &lockRect, NULL, 0);
00142                     if (SUCCEEDED(hr)) {
00143                         uint8_t* dst8 = (uint8_t*)lockRect.pBits;
00144                         uint8_t* src8 = frame->data[i];
00145                         CopyMemory(dst8, src8, lockRect.Pitch * _h[i]);
00146                         hr = _texture[i]->UnlockRect(0);
00147                     } else {
00148                         _log.warning(Poco::format("failed texture[%d] unlock", i));
00149                     }
00150                 }
00151             }
00152 
00153         } else {
00154             // パックド
00155             D3DLOCKED_RECT lockRect = {0};
00156             HRESULT hr = _texture[0]->LockRect(0, &lockRect, NULL, 0);
00157             if (SUCCEEDED(hr)) {
00158                 uint8_t* dst8 = (uint8_t*)lockRect.pBits;
00159                 uint8_t* src8 = frame->data[0];
00160                 CopyMemory(dst8, src8, lockRect.Pitch * _h[0]);
00161                 hr = _texture[0]->UnlockRect(0);
00162             } else {
00163                 _log.warning("failed lock texture");
00164             }
00165         }
00166         _frameNumber = frame->coded_picture_number;
00167     }
00168 
00169     void draw(const int x, const int y, int w = -1, int h = -1, int aspectMode = 0, DWORD col = 0xffffffff, int tx = 0, int ty = 0, int tw = -1, int th = -1) {
00170         if (w < 0) w = _w[0];
00171         if (h < 0) h = _h[0];
00172         int dx = 0;
00173         int dy = 0;
00174         switch (aspectMode) {
00175             case 0:
00176                 break;
00177 
00178             case 1:
00179                 // float srcZ =_w[0] / _h[0];
00180 
00181                 if (w < _w[0]) {
00182                     float z = F(w) / _w[0];
00183                     float hh = L(_h[0] * z);
00184                     dy = (h - hh) / 2;
00185                     h = hh;
00186                 } else if (h < _h[0]) {
00187                     float z = F(h) / _h[0];
00188                     float ww = L(_w[0] * z);
00189                     dx = (w - ww) / 2;
00190                     w = ww;
00191                 } else {
00192                     if (w > _w[0]) w = _w[0];
00193                     if (h > _h[0]) h = _h[0];
00194                 }
00195                 break;
00196             default:
00197                 w = _w[0];
00198                 h = _h[0];
00199         }
00200         if (tw == -1) tw = _w[0];
00201         if (th == -1) th = _h[0];
00202 
00203         LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00204         if (_texture[1]) {
00205             // プレナー
00206             VERTEX dst[] =
00207                 {
00208                     {F(x     + dx - 0.5), F(y     + dy - 0.5), 0.0f, 1.0f, col, toTexelU(tx     ), toTexelV(ty     )},
00209                     {F(x + w + dx - 0.5), F(y     + dy - 0.5), 0.0f, 1.0f, col, toTexelU(tx + tw), toTexelV(ty     )},
00210                     {F(x     + dx - 0.5), F(y + h + dy - 0.5), 0.0f, 1.0f, col, toTexelU(tx     ), toTexelV(ty + th)},
00211                     {F(x + w + dx - 0.5), F(y + h + dy - 0.5), 0.0f, 1.0f, col, toTexelU(tx + tw), toTexelV(ty + th)}
00212                 };
00213             device->SetTexture(0, _texture[0]);
00214             device->SetTexture(1, _texture[1]);
00215             device->SetTexture(2, _texture[2]);
00216             if (_fx) {
00217                 _fx->SetTechnique("conversionTech");
00218                 _fx->SetTexture("stage0", _texture[0]);
00219                 _fx->SetTexture("stage1", _texture[1]);
00220                 _fx->SetTexture("stage2", _texture[2]);
00221                 _fx->Begin(NULL, 0);
00222                 _fx->BeginPass(0);
00223             }
00224             device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, dst, sizeof(VERTEX));
00225             if (_fx) {
00226                 _fx->EndPass();
00227                 _fx->End();
00228             }
00229 
00230             device->SetTexture(0, NULL);
00231             device->SetTexture(1, NULL);
00232             device->SetTexture(2, NULL);
00233 
00234         } else {
00235             // パックド
00236             VERTEX dst[] =
00237                 {
00238                     {F(x     - 0.5), F(y     - 0.5), 0.0f, 1.0f, col, toTexelU(tx     ), toTexelV(ty     )},
00239                     {F(x + w - 0.5), F(y     - 0.5), 0.0f, 1.0f, col, toTexelU(tx + tw), toTexelV(ty     )},
00240                     {F(x     - 0.5), F(y + h - 0.5), 0.0f, 1.0f, col, toTexelU(tx     ), toTexelV(ty + th)},
00241                     {F(x + w - 0.5), F(y + h - 0.5), 0.0f, 1.0f, col, toTexelU(tx + tw), toTexelV(ty + th)}
00242                 };
00243             device->SetTexture(0, _texture[0]);
00244             device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, dst, sizeof(VERTEX));
00245             device->SetTexture(0, NULL);
00246         }
00247         // _renderer.drawFontTextureText(0, 0, 12, 16, 0xffffffff, Poco::format("COLOR: %08lx", col));
00248     }
00249 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines