svvitch
digital signage player
|
00001 #include "DSVideoRenderer.h" 00002 #include <Dvdmedia.h> 00003 00004 00005 #define WRITE_CLIPPED_BYTE(D, S) { int v = S; if (v < 0) v = 0; if (v > 255) v = 255; (D)=(BYTE)v; } 00006 00007 00008 DSVideoRenderer::DSVideoRenderer(Renderer& renderer, bool supportYUV2, LPUNKNOWN unk, HRESULT* result): 00009 CBaseVideoRenderer(__uuidof(CLSID_DSVideoRenderer), NAME("DSVideoRenderer"), unk, result), 00010 _log(Poco::Logger::get("")), _renderer(renderer), 00011 _supportYUV2(supportYUV2), _w(0), _h(0), _texture(NULL), _current(0), _readTime(0) 00012 { 00013 AddRef(); 00014 _format = D3DFMT_UNKNOWN; 00015 *result = S_OK; 00016 00017 } 00018 00019 DSVideoRenderer::‾DSVideoRenderer() { 00020 releaseTexture(); 00021 _log.information("*release video renderer"); 00022 } 00023 00024 void DSVideoRenderer::releaseTexture() { 00025 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00026 SAFE_RELEASE(_texture); 00027 } 00028 00029 bool DSVideoRenderer::getMediaTypeName(const CMediaType* pmt, string& type, D3DFORMAT* format) { 00030 bool result = false; 00031 if (IsEqualGUID(*pmt->Type(), MEDIATYPE_Video)) { 00032 if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_MPEG1Packet)) { 00033 type = "MPEG1-Packet"; 00034 result = false; 00035 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_MPEG1Payload)) { 00036 type = "MPEG1-Payload"; 00037 result = false; 00038 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_RGB24)) { 00039 type = "RGB24"; 00040 *format = D3DFMT_R8G8B8; 00041 result = false; 00042 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_RGB32)) { 00043 type = "RGB32"; 00044 *format = D3DFMT_X8R8G8B8; 00045 result = true; 00046 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_RGB555)) { 00047 type = "RGB555"; 00048 *format = D3DFMT_X1R5G5B5; 00049 result = false; 00050 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_RGB565)) { 00051 type = "RGB565"; 00052 *format = D3DFMT_R5G6B5; 00053 result = false; 00054 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_RGB8)) { 00055 type = "RGB8"; 00056 *format = D3DFMT_X8R8G8B8; 00057 result = false; 00058 00059 00060 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_YUY2)) { // Packed YUYV 00061 type = "YUY2"; 00062 *format = D3DFMT_YUY2; 00063 result = _supportYUV2; 00064 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_YUYV)) { // Packed 00065 type = "YUYV"; 00066 *format = D3DFMT_UNKNOWN; 00067 result = false; 00068 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_UYVY)) { // Packed 00069 type = "UYVY"; 00070 *format = D3DFMT_UNKNOWN; 00071 result = false; 00072 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_Y41P)) { // Packed 00073 type = "Y41P"; 00074 *format = D3DFMT_UNKNOWN; 00075 result = false; 00076 00077 00078 } else if (IsEqualGUID(*pmt->Subtype(), MEDIASUBTYPE_YV12)) { // Planer YVU 00079 type = "YV12"; 00080 *format = D3DFMT_UNKNOWN; 00081 result = false; 00082 00083 } else { 00084 //GUIDの見本 32315659-0000-0010-8000-00AA00389B71 00085 string serial; 00086 for (int i = 0; i < 8; i++) { 00087 serial += Poco::format(",%02?x", pmt->Subtype()->Data4[i]); 00088 } 00089 string guid = Poco::format("[%08?x,%04?x,%04?x%s]", pmt->Subtype()->Data1, pmt->Subtype()->Data2, pmt->Subtype()->Data3, serial); 00090 _log.warning(Poco::format("invalid media subtype: %s", guid)); 00091 } 00092 } 00093 return result; 00094 } 00095 00096 HRESULT DSVideoRenderer::CheckMediaType(const CMediaType* pmt) { 00097 CheckPointer(pmt, E_POINTER); 00098 if (!IsEqualGUID(*pmt->Type(), MEDIATYPE_Video)) { 00099 //string serial; 00100 //for (int i = 0; i < 8; i++) { 00101 // serial += Poco::format(",%02?x", pmt->FormatType()->Data4[i]); 00102 //} 00103 //string guid = Poco::format("[%08?x,%04?x,%04?x%s]", pmt->FormatType()->Data1, pmt->FormatType()->Data2, pmt->FormatType()->Data3, serial); 00104 //_log.warning(Poco::format("invalid format type: %s", guid)); 00105 return E_INVALIDARG; 00106 } 00107 00108 HRESULT hr = E_FAIL; 00109 long w = 0; 00110 long h = 0; 00111 int i = 0; 00112 RECT src ,target; 00113 string type; 00114 D3DFORMAT format; 00115 if (IsEqualGUID(*pmt->FormatType(), FORMAT_VideoInfo)) { 00116 VIDEOINFOHEADER* info = (VIDEOINFOHEADER*)pmt->Format(); 00117 w = info->bmiHeader.biWidth; 00118 h = info->bmiHeader.biHeight; 00119 i = 1; 00120 CopyRect(&src, &info->rcSource); 00121 CopyRect(&target, &info->rcTarget); 00122 } else if (IsEqualGUID(*pmt->FormatType(), FORMAT_VideoInfo2)) { 00123 VIDEOINFOHEADER2* info = (VIDEOINFOHEADER2*)pmt->Format(); 00124 w = info->bmiHeader.biWidth; 00125 h = info->bmiHeader.biHeight; 00126 i = 2; 00127 CopyRect(&src, &info->rcSource); 00128 CopyRect(&target, &info->rcTarget); 00129 } else if (IsEqualGUID(*pmt->FormatType(), FORMAT_MPEGVideo)) { 00130 MPEG1VIDEOINFO* info = (MPEG1VIDEOINFO*)pmt->Format(); 00131 w = info->hdr.bmiHeader.biWidth; 00132 h = info->hdr.bmiHeader.biHeight; 00133 i = 3; 00134 CopyRect(&src, &info->hdr.rcSource); 00135 CopyRect(&target, &info->hdr.rcTarget); 00136 } 00137 if (getMediaTypeName(pmt, type, &format)) { 00138 hr = S_OK; 00139 } 00140 string srcRect = Poco::format("(%ld,%ld,%ld,%ld)", src.left, src.top, src.right, src.bottom); 00141 string targetRect = Poco::format("(%ld,%ld,%ld,%ld)", target.left, target.top, target.right, target.bottom); 00142 _log.information(Poco::format("check media type[%d]: %s %ldx%ld %s %s", i, type, w, h, srcRect, targetRect)); 00143 return hr; 00144 } 00145 00146 HRESULT DSVideoRenderer::SetMediaType(const CMediaType* pmt) { 00147 HRESULT hr = E_FAIL; 00148 long w = 0; 00149 long h = 0; 00150 int i = 0; 00151 if (IsEqualGUID(*pmt->FormatType(), FORMAT_VideoInfo)) { 00152 VIDEOINFOHEADER* info = (VIDEOINFOHEADER*)pmt->Format(); 00153 w = info->bmiHeader.biWidth; 00154 h = info->bmiHeader.biHeight; 00155 i = 1; 00156 } else if (IsEqualGUID(*pmt->FormatType(), FORMAT_VideoInfo2)) { 00157 VIDEOINFOHEADER2* info = (VIDEOINFOHEADER2*)pmt->Format(); 00158 w = info->bmiHeader.biWidth; 00159 h = info->bmiHeader.biHeight; 00160 i = 2; 00161 } else if (IsEqualGUID(*pmt->FormatType(), FORMAT_MPEGVideo)) { 00162 MPEG1VIDEOINFO* info = (MPEG1VIDEOINFO*)pmt->Format(); 00163 w = info->hdr.bmiHeader.biWidth; 00164 h = info->hdr.bmiHeader.biHeight; 00165 i = 3; 00166 } 00167 if (w != 0 && h != 0) { 00168 releaseTexture(); 00169 string type; 00170 D3DFORMAT format; 00171 if (getMediaTypeName(pmt, type, &format)) { 00172 switch (format) { 00173 case D3DFMT_R8G8B8: 00174 case D3DFMT_X8R8G8B8: 00175 case D3DFMT_A8R8G8B8: 00176 case D3DFMT_YUY2: 00177 _format = format; 00178 _w = w; 00179 _h = h; 00180 _texture = _renderer.createTexture(_w, _h, D3DFMT_X8R8G8B8); 00181 if (_texture) hr = S_OK; 00182 break; 00183 } 00184 } 00185 _log.information(Poco::format("set media type[%d]: %s %ldx%ld", i, type, w, h)); 00186 } 00187 return hr; 00188 } 00189 00190 HRESULT DSVideoRenderer::DoRenderSample(IMediaSample* sample) { 00191 CheckPointer(sample, E_POINTER); 00192 CheckPointer(_texture, E_UNEXPECTED); 00193 00194 HRESULT hr = E_FAIL; 00195 AM_MEDIA_TYPE* type = NULL; 00196 sample->GetMediaType(&type); 00197 if (type) { 00198 _log.information("*change media type"); 00199 DeleteMediaType(type); 00200 } 00201 00202 LPBYTE src, dst; 00203 sample->GetPointer(&src); 00204 long size = sample->GetActualDataLength(); 00205 if (_texture) { 00206 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00207 _readTimer.start(); 00208 D3DLOCKED_RECT lockRect = {0}; 00209 if (SUCCEEDED(_texture->LockRect(0, &lockRect, 0, 0))) { 00210 dst = (LPBYTE)lockRect.pBits; 00211 switch (_format) { 00212 case D3DFMT_R8G8B8: 00213 break; 00214 case D3DFMT_X8R8G8B8: 00215 case D3DFMT_A8R8G8B8: 00216 CopyMemory(dst, src, size); 00217 break; 00218 case D3DFMT_YUY2: 00219 convertYUY2_RGB(dst, src, size); 00220 break; 00221 } 00222 _texture->UnlockRect(0); 00223 _current++; 00224 hr = S_OK; 00225 } else { 00226 _log.warning("failed capture texture lock"); 00227 } 00228 _readTime = _readTimer.getTime(); 00229 } else { 00230 hr = E_UNEXPECTED; 00231 } 00232 return hr; 00233 } 00234 00235 LPDIRECT3DTEXTURE9 DSVideoRenderer::getTexture() { 00236 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00237 return _texture; 00238 } 00239 00240 DWORD DSVideoRenderer::currentTime() { 00241 return _current; 00242 } 00243 00244 DWORD DSVideoRenderer::readTime() { 00245 return _readTime; 00246 } 00247 00253 void DSVideoRenderer::convertYUY2_RGB(LPBYTE dst, LPBYTE src, size_t len) { 00254 long pos = 0; 00255 int Y0, Y1, U, V; 00256 for (int i = 0; i < len; i += 4) { 00257 Y0 = 298 * (src[i + 0] - 16); 00258 Y1 = 298 * (src[i + 2] - 16); 00259 U = src[i + 1] - 128; 00260 V = src[i + 3] - 128; 00261 00262 WRITE_CLIPPED_BYTE(dst[pos++], (Y0 + 516 * U + 128) >> 8); // B 00263 WRITE_CLIPPED_BYTE(dst[pos++], (Y0 - 100 * U - 208 * V + 128) >> 8); // G 00264 WRITE_CLIPPED_BYTE(dst[pos++], (Y0 + 409 * V + 128) >> 8); // R 00265 // dst[pos++] = 0xff; 00266 pos++; 00267 00268 WRITE_CLIPPED_BYTE(dst[pos++], (Y1 + 516 * U + 128) >> 8); // B 00269 WRITE_CLIPPED_BYTE(dst[pos++], (Y1 - 100 * U - 208 * V + 128) >> 8); // G 00270 WRITE_CLIPPED_BYTE(dst[pos++], (Y1 + 409 * V + 128) >> 8); // R 00271 pos++; 00272 // dst[pos++] = 0xff; 00273 } 00274 } 00275 00276 long DSVideoRenderer::width() { 00277 return _w; 00278 } 00279 00280 long DSVideoRenderer::height() { 00281 return _h; 00282 } 00283 00285 float DSVideoRenderer::getDisplayAspectRatio() { 00286 if (_h > 0) { 00287 return F(_w) / _h; 00288 } 00289 return 0; 00290 } 00291 00292 void DSVideoRenderer::draw(const int x, const int y, int w, int h, int aspectMode, int flipMode, DWORD col, int tx, int ty, int tw, int th) { 00293 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00294 if (w < 0) w = _w; 00295 if (h < 0) h = _h; 00296 int dx = 0; 00297 int dy = 0; 00298 switch (aspectMode) { 00299 case 0: 00300 break; 00301 00302 case 1: 00303 // float srcZ =_w[0] / _h[0]; 00304 00305 if (w < _w) { 00306 float z = F(w) / _w; 00307 float hh = L(_h * z); 00308 dy = (h - hh) / 2; 00309 h = hh; 00310 } else if (h < _h) { 00311 float z = F(h) / _h; 00312 float ww = L(_w * z); 00313 dx = (w - ww) / 2; 00314 w = ww; 00315 } else { 00316 if (w > _w) w = _w; 00317 if (h > _h) h = _h; 00318 } 00319 break; 00320 default: 00321 w = _w; 00322 h = _h; 00323 } 00324 if (tw == -1) tw = _w; 00325 if (th == -1) th = _h; 00326 00327 // 上下反転して描画 00328 _renderer.drawTexture(x + dx, y + dy, w, h, tx, ty, tx + tw, ty + th, _texture, flipMode, col, col, col, col); 00329 }