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