00001 //=========================================================================== 00002 //Copyright (C) 2004 Zentaro Kavanagh 00003 // 00004 //Redistribution and use in source and binary forms, with or without 00005 //modification, are permitted provided that the following conditions 00006 //are met: 00007 // 00008 //- Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // 00011 //- Redistributions in binary form must reproduce the above copyright 00012 // notice, this list of conditions and the following disclaimer in the 00013 // documentation and/or other materials provided with the distribution. 00014 // 00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 00016 // may be used to endorse or promote products derived from this software 00017 // without specific prior written permission. 00018 // 00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00022 //PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR 00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 //=========================================================================== 00031 #include "stdafx.h" 00032 #include "subtitlevmr9filter.h" 00033 00034 00035 //COM Factory Template 00036 CFactoryTemplate g_Templates[] = 00037 { 00038 { 00039 L"Subtitle VMR9 Filter", // Name 00040 &CLSID_SubtitleVMR9Filter, // CLSID 00041 SubtitleVMR9Filter::CreateInstance, // Method to create an instance of Speex Decoder 00042 NULL, // Initialization function 00043 NULL // Set-up information (for filters) 00044 } 00045 00046 }; 00047 00048 // Generic way of determining the number of items in the template 00049 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 00050 00051 CUnknown* WINAPI SubtitleVMR9Filter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 00052 { 00053 //This routine is the COM implementation to create a new Filter 00054 SubtitleVMR9Filter *pNewObject = new SubtitleVMR9Filter(); 00055 if (pNewObject == NULL) { 00056 *pHr = E_OUTOFMEMORY; 00057 } 00058 return pNewObject; 00059 } 00060 00061 //***********************&!*(#&$()*&!@()*#&!@()*#&()!@*&#)(!@*&#()*!@&#)(*!@&#)*(!@ 00062 //This esentially disables the filter... 00063 HRESULT SubtitleVMR9Filter::Receive(IMediaSample *pMediaSample) { 00064 return S_OK; 00065 } 00066 //&)(*Q&#$()*!@&#$()!*@&#)(*!@&#)(*!@&#)(*&!@)#(*&!@)(#*&()!@*#&)(!*@&#()!*@&#()!@*&# 00067 00068 SubtitleVMR9Filter::SubtitleVMR9Filter(void) 00069 : CBaseRenderer(CLSID_SubtitleVMR9Filter, NAME("Subtitle VMR9 Filter") ,NULL,&mHR) 00070 , mBitmapMixer(NULL) 00071 , mVideoWindow(NULL) 00072 , mWindowLess(NULL) 00073 { 00074 //debugLog.open("G:\\logs\\vmr9_subs.log", ios_base::out); 00075 //mOutputPin = new SubtitleVMR9OutputPin(this, m_pLock, NAME("SubtitleVMR9OutputPin"), L"Subtitle Out"); 00076 } 00077 00078 SubtitleVMR9Filter::~SubtitleVMR9Filter(void) 00079 { 00080 //debugLog<<"Destructor for subtitle renderer"<<endl; 00081 //debugLog.close(); 00082 00083 if (mBitmapMixer != NULL) { 00084 mBitmapMixer->Release(); 00085 } 00086 00087 if (mVideoWindow != NULL) { 00088 mVideoWindow->Release(); 00089 } 00090 00091 if (mWindowLess != NULL) { 00092 mWindowLess->Release(); 00093 } 00094 } 00095 00096 STDMETHODIMP SubtitleVMR9Filter::GetState(DWORD dw, FILTER_STATE *pState) 00097 { 00098 CheckPointer(pState, E_POINTER); 00099 *pState = m_State; 00100 if (m_State == State_Paused) { 00101 return VFW_S_CANT_CUE; 00102 } else { 00103 return S_OK; 00104 } 00105 } 00106 int SubtitleVMR9Filter::GetPinCount(void) { 00107 return 1; 00108 } 00109 CBasePin* SubtitleVMR9Filter::GetPin(int inPinNo) { 00110 if (inPinNo == 0) { 00111 return CBaseRenderer::GetPin(inPinNo); 00112 } else { 00113 return NULL; 00114 } 00115 } 00116 00117 HRESULT SubtitleVMR9Filter::CheckMediaType(const CMediaType* inMediaType) { 00118 return S_OK; 00119 } 00120 HRESULT SubtitleVMR9Filter::DoRenderSample(IMediaSample* inMediaSample) { 00121 //debugLog<<"DoRenderSample : "<<endl; 00122 LONGLONG locStart, locEnd; 00123 inMediaSample->GetTime(&locStart, &locEnd); 00124 //debugLog<<"DoRenderSample : Time = "<<locStart<<" to "<<locEnd<<endl; 00125 inMediaSample->GetMediaTime(&locStart, &locEnd); 00126 //debugLog<<"DoRenderSample : Media Time = "<<locStart<<" to "<<locEnd<<endl; 00127 static int c = 0; 00128 const int hm = 50; 00129 if (mBitmapMixer == NULL) { 00130 IFilterGraph* locFilterGraph = NULL; 00131 locFilterGraph = GetFilterGraph(); 00132 00133 00134 IBaseFilter* locVMR9 = NULL; 00135 HRESULT locHR = locFilterGraph->FindFilterByName(L"Video Mixing Renderer 9", &locVMR9); 00136 if (locVMR9 != NULL) { 00137 //debugLog<<"DoRenderSample : Getting VMR9 pointer..."<<endl; 00138 HRESULT locHR = locVMR9->QueryInterface(IID_IVMRMixerBitmap9, (void**)&mBitmapMixer); 00139 locHR = locVMR9->QueryInterface(IID_IVMRWindowlessControl9, (void**)&mWindowLess); 00140 00141 locHR = locVMR9->QueryInterface(IID_IVideoWindow, (void**)&mVideoWindow); 00142 locVMR9->Release(); 00143 } else { 00144 return S_OK; 00145 } 00146 } else { 00147 /*c++; 00148 string x; 00149 switch ((c / hm) % 4) { 00150 case 0: 00151 x = "One"; 00152 SetSubtitle(x); 00153 break; 00154 case 1: 00155 x = "Two"; 00156 SetSubtitle(x); 00157 break; 00158 00159 case 2: 00160 x = "Three"; 00161 SetSubtitle(x); 00162 break; 00163 case 3: 00164 x = "Four"; 00165 SetSubtitle(x); 00166 break; 00167 default: 00168 break; 00169 00170 00171 }*/ 00172 00173 if (inMediaSample->GetActualDataLength() > 0) { 00174 wchar_t* locStr = NULL; 00175 BYTE* locBuff = NULL; 00176 inMediaSample->GetPointer(&locBuff); 00177 locStr = new wchar_t[inMediaSample->GetActualDataLength() / sizeof(wchar_t)]; 00178 memcpy((void*)locStr, (const void*) locBuff, inMediaSample->GetActualDataLength()); 00179 wstring x = locStr; 00180 //debugLog<<"DoRenderSample : Subtile = "<<x<<endl; 00181 SetSubtitle(x); 00182 //debugLog<<"DoRenderSample : SetSubtitle Returns"<<endl<<endl; 00183 delete locStr; 00184 } else { 00185 //debugLog<<"DoRenderSample : Clearing Subtitle..."<<endl; 00186 SetSubtitle(L""); 00187 } 00188 00189 00190 return S_OK; 00191 } 00192 //debugLog<<"DoRenderSample : NEVER SHOULD BE HERE !!!!!!"<<endl; 00193 } 00194 00195 00196 00197 00198 HRESULT SubtitleVMR9Filter::SetSubtitle(wstring inSubtitle) { 00199 // LONG cx, cy; 00200 // HRESULT locHR; 00201 00202 // // Read the default video size 00203 // //hr = pWC->GetNativeVideoSize(&cx, &cy, NULL, NULL); 00204 // //if (FAILED(hr)) 00205 // //{ 00206 // // Msg(TEXT("GetNativeVideoSize FAILED! hr=0x%x\r\n"), hr); 00207 // // return hr; 00208 // //} 00209 00210 // // Create a device context compatible with the current window 00211 00212 //locHR = mBitmapMixer->GetAlphaBitmapParameters(&mAlphaBitmap); 00213 // //HDC hdc = GetDC(hwndApp); 00214 // HDC locHDCBitmap = CreateCompatibleDC(mAlphaBitmap.hdc); 00215 00216 // // Write with a known font by selecting it into our HDC 00217 // HFONT locFontHandle = (HFONT) SelectObject(locHDCBitmap, g_hFont); 00218 00219 // // Determine the length of the string, then determine the 00220 // // dimensions (in pixels) of the character string using the 00221 // // currently selected font. These dimensions are used to create 00222 // // a bitmap below. 00223 // int locLength, locTextBmpWidth, locTextBmpHeight; 00224 // SIZE sz={0}; 00225 // locLength = inSubtitle.size(); 00226 // GetTextExtentPoint32(locHDCBitmap, inSubtitle.c_str(), locLength, &sz); 00227 // locTextBmpHeight = sz.cy; 00228 // locTextBmpWidth = sz.cx; 00229 00230 // // Create a new bitmap that is compatible with the current window 00231 // HBITMAP locBitmapHandle = CreateCompatibleBitmap(mAlphaBitmap.hdc, locTextBmpWidth, locTextBmpHeight); 00232 // //ReleaseDC(hwndApp, hdc); 00233 00234 // // Select our bitmap into the device context and save the old one 00235 // BITMAP locBitmap; 00236 // HBITMAP locOldBitmapHandle; 00237 // GetObject(locBitmapHandle, sizeof(locBitmap), &locBitmap); 00238 // locOldBitmapHandle = (HBITMAP)SelectObject(locBitmapHandle, locBitmapHandle); 00239 00240 // // Set initial bitmap settings 00241 // RECT rcText; 00242 // SetRect(&rcText, 0, 0, nTextBmpWidth, nTextBmpHeight); 00243 // SetBkColor(locBitmapHandle, RGB(255, 255, 255)); // Pure white background 00244 // SetTextColor(locBitmapHandle, g_rgbColors); // Write text with requested color 00245 00246 // // Draw the requested text string onto the bitmap 00247 // TextOut(locBitmapHandle, 0, 0, inSubtitle.c_str(), locLength); 00248 00249 // // Configure the VMR's bitmap structure 00250 // //VMR9AlphaBitmap bmpInfo; 00251 // ZeroMemory(&mAlphaBitmap, sizeof(mAlphaBitmap) ); 00252 // mAlphaBitmap.dwFlags = VMRBITMAP_HDC; 00253 // mAlphaBitmap.hdc = locHDCBitmap; // DC which has selected our bitmap 00254 00255 // // Remember the width of this new bitmap 00256 // g_nImageWidth = bm.bmWidth; 00257 00258 // // Save the ratio of the bitmap's width to the width of the video file. 00259 // // This value is used to reposition the bitmap in composition space. 00260 // g_fBitmapCompWidth = (float)g_nImageWidth / (float)cx; 00261 00262 // // Display the bitmap in the bottom right corner. 00263 // // rSrc specifies the source rectangle in the GDI device context 00264 // // rDest specifies the destination rectangle in composition space (0.0f to 1.0f) 00265 // mAlphaBitmap.rDest.left = 0.0f + X_EDGE_BUFFER; 00266 // mAlphaBitmap.rDest.right = 1.0f - X_EDGE_BUFFER; 00267 // mAlphaBitmap.rDest.top = (float)(cy - bm.bmHeight) / (float)cy - Y_EDGE_BUFFER; 00268 // bmAlphaBitmap.rDest.bottom = 1.0f - Y_EDGE_BUFFER; 00269 // mAlphaBitmap.rSrc = rcText; 00270 00271 // // Transparency value 1.0 is opaque, 0.0 is transparent. 00272 // mAlphaBitmap.fAlpha = TRANSPARENCY_VALUE; 00273 00274 // // Set the COLORREF so that the bitmap outline will be transparent 00275 // SetColorRef(mAlphaBitmap); 00276 00277 // // Give the bitmap to the VMR for display 00278 // locHR = mBitmapMixer->SetAlphaBitmap(&mAlphaBitmap); 00279 // if (FAILED(hr)) 00280 // Msg(TEXT("SetAlphaBitmap FAILED! hr=0x%x\r\n\r\n%s\0"), hr, 00281 // STR_VMR_DISPLAY_WARNING); 00282 00283 // // Select the initial objects back into our device context 00284 // DeleteObject(SelectObject(locBitmapHDC,locOldBitmapHandle )); 00285 // SelectObject(locHDCBitmap, locFont); 00286 00287 // // Clean up resources 00288 // DeleteObject(hbm); 00289 // DeleteDC(hdcBmp); 00290 00291 // return hr; 00292 00293 00294 // Text font information 00295 HFONT g_hFont=0; 00296 LONG g_lFontPointSize = DEFAULT_FONT_SIZE; 00297 COLORREF g_rgbColors = DEFAULT_FONT_COLOR; 00298 TCHAR g_szFontName[100] = {DEFAULT_FONT_NAME}; 00299 TCHAR g_szFontStyle[32] = {DEFAULT_FONT_STYLE}; 00300 00301 LONG cx, cy; 00302 HRESULT hr; 00303 00304 // Read the default video size 00305 if (mWindowLess != NULL) { 00306 hr = mWindowLess->GetNativeVideoSize(&cx, &cy, NULL, NULL); 00307 } else { 00308 mVideoWindow->get_Width(&cx); 00309 mVideoWindow->get_Height(&cy); 00310 } 00311 //if (FAILED(hr)) 00312 //{ 00313 // Msg(TEXT("GetNativeVideoSize FAILED! hr=0x%x\r\n"), hr); 00314 // return hr; 00315 //} 00316 00317 // Create a device context compatible with the current window 00318 hr = mBitmapMixer->GetAlphaBitmapParameters(&mAlphaBitmap); 00319 //HWND hwndApp; 00320 //OAHWND oah; 00321 //mVideoWindow->get_Owner(&oah); 00322 HDC hdc = GetDC(NULL); 00323 //HDC hdc = mAlphaBitmap.hdc; 00324 HDC hdcBmp = CreateCompatibleDC(hdc); 00325 00326 // Write with a known font by selecting it into our HDC 00327 HFONT hOldFont = (HFONT) SelectObject(hdcBmp, g_hFont); 00328 00329 // Determine the length of the string, then determine the 00330 // dimensions (in pixels) of the character string using the 00331 // currently selected font. These dimensions are used to create 00332 // a bitmap below. 00333 int nLength, nTextBmpWidth, nTextBmpHeight; 00334 SIZE sz={0}; 00335 00336 TCHAR* szNewText = (TCHAR*)inSubtitle.c_str();//_T("Annodex Me Baby !");//inSubtitle.c_str(); 00337 nLength = _tcslen(szNewText); ;//(int) inSubtitle.size(); 00338 00339 GetTextExtentPoint32(hdcBmp, szNewText, nLength, &sz); 00340 nTextBmpHeight = sz.cy; 00341 nTextBmpWidth = sz.cx; 00342 00343 // Create a new bitmap that is compatible with the current window 00344 HBITMAP hbm = CreateCompatibleBitmap(hdc, nTextBmpWidth, nTextBmpHeight); 00345 //ReleaseDC(hwndApp, hdc); 00346 00347 // Select our bitmap into the device context and save the old one 00348 BITMAP bm; 00349 HBITMAP hbmOld; 00350 GetObject(hbm, sizeof(bm), &bm); 00351 hbmOld = (HBITMAP)SelectObject(hdcBmp, hbm); 00352 00353 // Set initial bitmap settings 00354 RECT rcText; 00355 SetRect(&rcText, 0, 0, nTextBmpWidth, nTextBmpHeight); 00356 SetBkColor(hdcBmp, RGB(255, 255, 255)); // Pure white background 00357 SetTextColor(hdcBmp, g_rgbColors); // Write text with requested color 00358 00359 // Draw the requested text string onto the bitmap 00360 BOOL ret = TextOut(hdcBmp, 0, 0, szNewText, nLength); 00361 00362 // Configure the VMR's bitmap structure 00363 VMR9AlphaBitmap bmpInfo; 00364 ZeroMemory(&bmpInfo, sizeof(bmpInfo) ); 00365 bmpInfo.dwFlags = VMRBITMAP_HDC; 00366 bmpInfo.hdc = hdcBmp; // DC which has selected our bitmap 00367 00368 // Remember the width of this new bitmap 00369 //g_nImageWidth = bm.bmWidth; 00370 00371 // Save the ratio of the bitmap's width to the width of the video file. 00372 // This value is used to reposition the bitmap in composition space. 00373 //g_fBitmapCompWidth = (float)g_nImageWidth / (float)cx; 00374 00375 // Display the bitmap in the bottom right corner. 00376 // rSrc specifies the source rectangle in the GDI device context 00377 // rDest specifies the destination rectangle in composition space (0.0f to 1.0f) 00378 00379 const float X_EDGE_BUFFER=0.05f; // Pixel buffer between bitmap and window edge 00380 // (represented in composition space [0 - 1.0f]) 00381 const float Y_EDGE_BUFFER=0.05f; 00382 00383 bmpInfo.rDest.left = 0.0f + X_EDGE_BUFFER; 00384 bmpInfo.rDest.right = 1.0f - X_EDGE_BUFFER; 00385 bmpInfo.rDest.top = (float)(cy - bm.bmHeight) / (float)cy - Y_EDGE_BUFFER; 00386 //bmpInfo.rDest.top = (float)(200.0f - bm.bmHeight) / (float)200.0f - Y_EDGE_BUFFER; 00387 //bmpInfo.rDest.top = 0.8f;//(float)(200.0f - bm.bmHeight) / (float)200.0f - Y_EDGE_BUFFER; 00388 bmpInfo.rDest.bottom = 1.0f - Y_EDGE_BUFFER; 00389 bmpInfo.rSrc = rcText; 00390 00391 // Transparency value 1.0 is opaque, 0.0 is transparent. 00392 bmpInfo.fAlpha = TRANSPARENCY_VALUE; 00393 00394 // Set the COLORREF so that the bitmap outline will be transparent 00395 SetColorRef(bmpInfo); 00396 00397 // Give the bitmap to the VMR for display 00398 hr = mBitmapMixer->SetAlphaBitmap(&bmpInfo); 00399 //if (FAILED(hr)) 00400 //Msg(TEXT("SetAlphaBitmap FAILED! hr=0x%x\r\n\r\n%s\0"), hr, 00401 // STR_VMR_DISPLAY_WARNING); 00402 00403 // Select the initial objects back into our device context 00404 DeleteObject(SelectObject(hdcBmp, hbmOld)); 00405 SelectObject(hdc, hOldFont); 00406 00407 // Clean up resources 00408 DeleteObject(hbm); 00409 DeleteDC(hdcBmp); 00410 00411 //debugLog<<"SetSubtitle : End of method: hr = "<<hr<<endl; 00412 return hr; 00413 } 00414 00415 void SubtitleVMR9Filter::SetColorRef(VMR9AlphaBitmap& bmpInfo) 00416 { 00417 // Set the COLORREF so that the bitmap outline will be transparent 00418 bmpInfo.clrSrcKey = RGB(255, 255, 255); // Pure white 00419 bmpInfo.dwFlags |= VMRBITMAP_SRCCOLORKEY; 00420 }