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