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 00032 #include "stdafx.h" 00033 #include "subtitlevmr9outputpin.h" 00034 00035 SubtitleVMR9OutputPin::SubtitleVMR9OutputPin(SubtitleVMR9Filter* inParentFilter, CCritSec* inFilterLock, CHAR* inObjectName, LPCWSTR inPinDisplayName) 00036 : CBasePin(inObjectName, inParentFilter, inFilterLock, &mHR, inPinDisplayName, PINDIR_OUTPUT) 00037 , mParentFilter(inParentFilter) 00038 , mBitmapMixer(NULL) 00039 { 00040 } 00041 00042 SubtitleVMR9OutputPin::~SubtitleVMR9OutputPin(void) 00043 { 00044 } 00045 00046 HRESULT SubtitleVMR9OutputPin::CheckConnect(IPin* inPin) { 00047 //Query for the video mixing bitmap interface 00048 //HRESULT locHR = inPin->QueryInterface(IID_IVMRMixerBitmap9, (void**)&mBitmapMixer); 00049 //if (locHR == S_OK) { 00050 return S_OK; 00051 //} else { 00052 // return S_FALSE; 00053 //} 00054 00055 00056 } 00057 void SubtitleVMR9OutputPin::FillMediaType(CMediaType* outMediaType) { 00058 outMediaType->SetType(&MEDIATYPE_Video); 00059 outMediaType->SetSubtype(&MEDIASUBTYPE_YV12); 00060 outMediaType->SetFormatType(&FORMAT_VideoInfo); 00061 outMediaType->SetTemporalCompression(FALSE); 00062 outMediaType->SetSampleSize(0); 00063 00064 } 00065 HRESULT SubtitleVMR9OutputPin::GetMediaType(int inPosition, CMediaType *outMediaType) { 00066 00067 if (inPosition < 0) { 00068 return E_INVALIDARG; 00069 } 00070 00071 if (inPosition == 0) { 00072 FillMediaType(outMediaType); 00073 VIDEOINFOHEADER* locVideoFormat = (VIDEOINFOHEADER*)outMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)); 00074 FillVideoInfoHeader(locVideoFormat); 00075 return S_OK; 00076 } else { 00077 return VFW_S_NO_MORE_ITEMS; 00078 } 00079 } 00080 00081 bool SubtitleVMR9OutputPin::FillVideoInfoHeader(VIDEOINFOHEADER* inFormatBuffer) { 00082 00083 00084 inFormatBuffer->AvgTimePerFrame = (UNITS * 1) / 25; 00085 inFormatBuffer->dwBitRate = 0; 00086 00087 inFormatBuffer->bmiHeader.biBitCount = 12; //12 bits per pixel 00088 inFormatBuffer->bmiHeader.biClrImportant = 0; //All colours important 00089 inFormatBuffer->bmiHeader.biClrUsed = 0; //Use max colour depth 00090 inFormatBuffer->bmiHeader.biCompression = MAKEFOURCC('Y','V','1','2'); 00091 inFormatBuffer->bmiHeader.biHeight = 0; //Not sure 00092 inFormatBuffer->bmiHeader.biPlanes = 1; //Must be 1 00093 inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //????? Size of what ? 00094 inFormatBuffer->bmiHeader.biSizeImage = 0; //Size in bytes of image ?? 00095 inFormatBuffer->bmiHeader.biWidth = 0; 00096 inFormatBuffer->bmiHeader.biXPelsPerMeter = 2000; //Fuck knows 00097 inFormatBuffer->bmiHeader.biYPelsPerMeter = 2000; //" " " " " 00098 00099 inFormatBuffer->rcSource.top = 0; 00100 inFormatBuffer->rcSource.bottom = 0; 00101 inFormatBuffer->rcSource.left = 0; 00102 inFormatBuffer->rcSource.right = 0; 00103 00104 inFormatBuffer->rcTarget.top = 0; 00105 inFormatBuffer->rcTarget.bottom = 0; 00106 inFormatBuffer->rcTarget.left = 0; 00107 inFormatBuffer->rcTarget.right = 0; 00108 00109 inFormatBuffer->dwBitErrorRate=0; 00110 return true; 00111 } 00112 HRESULT SubtitleVMR9OutputPin::CheckMediaType(const CMediaType *pmt) { 00113 //Fix this up after testing. 00114 return S_OK; 00115 } 00116 00117 STDMETHODIMP SubtitleVMR9OutputPin::BeginFlush() { 00118 return S_OK; 00119 } 00120 STDMETHODIMP SubtitleVMR9OutputPin::EndFlush() { 00121 return S_OK; 00122 } 00123 00124 HRESULT SubtitleVMR9OutputPin::SetSubtitle(wstring inSubtitle) { 00125 // LONG cx, cy; 00126 // HRESULT locHR; 00127 00128 // // Read the default video size 00129 // //hr = pWC->GetNativeVideoSize(&cx, &cy, NULL, NULL); 00130 // //if (FAILED(hr)) 00131 // //{ 00132 // // Msg(TEXT("GetNativeVideoSize FAILED! hr=0x%x\r\n"), hr); 00133 // // return hr; 00134 // //} 00135 00136 // // Create a device context compatible with the current window 00137 00138 //locHR = mBitmapMixer->GetAlphaBitmapParameters(&mAlphaBitmap); 00139 // //HDC hdc = GetDC(hwndApp); 00140 // HDC locHDCBitmap = CreateCompatibleDC(mAlphaBitmap.hdc); 00141 00142 // // Write with a known font by selecting it into our HDC 00143 // HFONT locFontHandle = (HFONT) SelectObject(locHDCBitmap, g_hFont); 00144 00145 // // Determine the length of the string, then determine the 00146 // // dimensions (in pixels) of the character string using the 00147 // // currently selected font. These dimensions are used to create 00148 // // a bitmap below. 00149 // int locLength, locTextBmpWidth, locTextBmpHeight; 00150 // SIZE sz={0}; 00151 // locLength = inSubtitle.size(); 00152 // GetTextExtentPoint32(locHDCBitmap, inSubtitle.c_str(), locLength, &sz); 00153 // locTextBmpHeight = sz.cy; 00154 // locTextBmpWidth = sz.cx; 00155 00156 // // Create a new bitmap that is compatible with the current window 00157 // HBITMAP locBitmapHandle = CreateCompatibleBitmap(mAlphaBitmap.hdc, locTextBmpWidth, locTextBmpHeight); 00158 // //ReleaseDC(hwndApp, hdc); 00159 00160 // // Select our bitmap into the device context and save the old one 00161 // BITMAP locBitmap; 00162 // HBITMAP locOldBitmapHandle; 00163 // GetObject(locBitmapHandle, sizeof(locBitmap), &locBitmap); 00164 // locOldBitmapHandle = (HBITMAP)SelectObject(locBitmapHandle, locBitmapHandle); 00165 00166 // // Set initial bitmap settings 00167 // RECT rcText; 00168 // SetRect(&rcText, 0, 0, nTextBmpWidth, nTextBmpHeight); 00169 // SetBkColor(locBitmapHandle, RGB(255, 255, 255)); // Pure white background 00170 // SetTextColor(locBitmapHandle, g_rgbColors); // Write text with requested color 00171 00172 // // Draw the requested text string onto the bitmap 00173 // TextOut(locBitmapHandle, 0, 0, inSubtitle.c_str(), locLength); 00174 00175 // // Configure the VMR's bitmap structure 00176 // //VMR9AlphaBitmap bmpInfo; 00177 // ZeroMemory(&mAlphaBitmap, sizeof(mAlphaBitmap) ); 00178 // mAlphaBitmap.dwFlags = VMRBITMAP_HDC; 00179 // mAlphaBitmap.hdc = locHDCBitmap; // DC which has selected our bitmap 00180 00181 // // Remember the width of this new bitmap 00182 // g_nImageWidth = bm.bmWidth; 00183 00184 // // Save the ratio of the bitmap's width to the width of the video file. 00185 // // This value is used to reposition the bitmap in composition space. 00186 // g_fBitmapCompWidth = (float)g_nImageWidth / (float)cx; 00187 00188 // // Display the bitmap in the bottom right corner. 00189 // // rSrc specifies the source rectangle in the GDI device context 00190 // // rDest specifies the destination rectangle in composition space (0.0f to 1.0f) 00191 // mAlphaBitmap.rDest.left = 0.0f + X_EDGE_BUFFER; 00192 // mAlphaBitmap.rDest.right = 1.0f - X_EDGE_BUFFER; 00193 // mAlphaBitmap.rDest.top = (float)(cy - bm.bmHeight) / (float)cy - Y_EDGE_BUFFER; 00194 // bmAlphaBitmap.rDest.bottom = 1.0f - Y_EDGE_BUFFER; 00195 // mAlphaBitmap.rSrc = rcText; 00196 00197 // // Transparency value 1.0 is opaque, 0.0 is transparent. 00198 // mAlphaBitmap.fAlpha = TRANSPARENCY_VALUE; 00199 00200 // // Set the COLORREF so that the bitmap outline will be transparent 00201 // SetColorRef(mAlphaBitmap); 00202 00203 // // Give the bitmap to the VMR for display 00204 // locHR = mBitmapMixer->SetAlphaBitmap(&mAlphaBitmap); 00205 // if (FAILED(hr)) 00206 // Msg(TEXT("SetAlphaBitmap FAILED! hr=0x%x\r\n\r\n%s\0"), hr, 00207 // STR_VMR_DISPLAY_WARNING); 00208 00209 // // Select the initial objects back into our device context 00210 // DeleteObject(SelectObject(locBitmapHDC,locOldBitmapHandle )); 00211 // SelectObject(locHDCBitmap, locFont); 00212 00213 // // Clean up resources 00214 // DeleteObject(hbm); 00215 // DeleteDC(hdcBmp); 00216 00217 // return hr; 00218 00219 00220 // Text font information 00221 HFONT g_hFont=0; 00222 LONG g_lFontPointSize = DEFAULT_FONT_SIZE; 00223 COLORREF g_rgbColors = DEFAULT_FONT_COLOR; 00224 TCHAR g_szFontName[100] = {DEFAULT_FONT_NAME}; 00225 TCHAR g_szFontStyle[32] = {DEFAULT_FONT_STYLE}; 00226 00227 LONG cx, cy; 00228 HRESULT hr; 00229 00230 // Read the default video size 00231 //hr = pWC->GetNativeVideoSize(&cx, &cy, NULL, NULL); 00232 //if (FAILED(hr)) 00233 //{ 00234 // Msg(TEXT("GetNativeVideoSize FAILED! hr=0x%x\r\n"), hr); 00235 // return hr; 00236 //} 00237 00238 // Create a device context compatible with the current window 00239 hr = mBitmapMixer->GetAlphaBitmapParameters(&mAlphaBitmap); 00240 HDC hdc = mAlphaBitmap.hdc; 00241 HDC hdcBmp = CreateCompatibleDC(hdc); 00242 00243 // Write with a known font by selecting it into our HDC 00244 HFONT hOldFont = (HFONT) SelectObject(hdcBmp, g_hFont); 00245 00246 // Determine the length of the string, then determine the 00247 // dimensions (in pixels) of the character string using the 00248 // currently selected font. These dimensions are used to create 00249 // a bitmap below. 00250 int nLength, nTextBmpWidth, nTextBmpHeight; 00251 SIZE sz={0}; 00252 nLength = (int) inSubtitle.size(); 00253 TCHAR* szNewText = _T("Blah blah");//inSubtitle.c_str(); 00254 GetTextExtentPoint32(hdcBmp, szNewText, nLength, &sz); 00255 nTextBmpHeight = sz.cy; 00256 nTextBmpWidth = sz.cx; 00257 00258 // Create a new bitmap that is compatible with the current window 00259 HBITMAP hbm = CreateCompatibleBitmap(hdc, nTextBmpWidth, nTextBmpHeight); 00260 //ReleaseDC(hwndApp, hdc); 00261 00262 // Select our bitmap into the device context and save the old one 00263 BITMAP bm; 00264 HBITMAP hbmOld; 00265 GetObject(hbm, sizeof(bm), &bm); 00266 hbmOld = (HBITMAP)SelectObject(hdcBmp, hbm); 00267 00268 // Set initial bitmap settings 00269 RECT rcText; 00270 SetRect(&rcText, 0, 0, nTextBmpWidth, nTextBmpHeight); 00271 SetBkColor(hdcBmp, RGB(255, 255, 255)); // Pure white background 00272 SetTextColor(hdcBmp, g_rgbColors); // Write text with requested color 00273 00274 // Draw the requested text string onto the bitmap 00275 TextOut(hdcBmp, 0, 0, szNewText, nLength); 00276 00277 // Configure the VMR's bitmap structure 00278 VMR9AlphaBitmap bmpInfo; 00279 ZeroMemory(&bmpInfo, sizeof(bmpInfo) ); 00280 bmpInfo.dwFlags = VMRBITMAP_HDC; 00281 bmpInfo.hdc = hdcBmp; // DC which has selected our bitmap 00282 00283 // Remember the width of this new bitmap 00284 //g_nImageWidth = bm.bmWidth; 00285 00286 // Save the ratio of the bitmap's width to the width of the video file. 00287 // This value is used to reposition the bitmap in composition space. 00288 //g_fBitmapCompWidth = (float)g_nImageWidth / (float)cx; 00289 00290 // Display the bitmap in the bottom right corner. 00291 // rSrc specifies the source rectangle in the GDI device context 00292 // rDest specifies the destination rectangle in composition space (0.0f to 1.0f) 00293 00294 const float X_EDGE_BUFFER=0.05f; // Pixel buffer between bitmap and window edge 00295 // (represented in composition space [0 - 1.0f]) 00296 const float Y_EDGE_BUFFER=0.05f; 00297 00298 bmpInfo.rDest.left = 0.0f + X_EDGE_BUFFER; 00299 bmpInfo.rDest.right = 1.0f - X_EDGE_BUFFER; 00300 bmpInfo.rDest.top = (float)(cy - bm.bmHeight) / (float)cy - Y_EDGE_BUFFER; 00301 bmpInfo.rDest.bottom = 1.0f - Y_EDGE_BUFFER; 00302 bmpInfo.rSrc = rcText; 00303 00304 // Transparency value 1.0 is opaque, 0.0 is transparent. 00305 bmpInfo.fAlpha = TRANSPARENCY_VALUE; 00306 00307 // Set the COLORREF so that the bitmap outline will be transparent 00308 SetColorRef(bmpInfo); 00309 00310 // Give the bitmap to the VMR for display 00311 hr = mBitmapMixer->SetAlphaBitmap(&bmpInfo); 00312 if (FAILED(hr)) 00313 //Msg(TEXT("SetAlphaBitmap FAILED! hr=0x%x\r\n\r\n%s\0"), hr, 00314 // STR_VMR_DISPLAY_WARNING); 00315 00316 // Select the initial objects back into our device context 00317 DeleteObject(SelectObject(hdcBmp, hbmOld)); 00318 SelectObject(hdc, hOldFont); 00319 00320 // Clean up resources 00321 DeleteObject(hbm); 00322 DeleteDC(hdcBmp); 00323 00324 return hr; 00325 } 00326 00327 void SubtitleVMR9OutputPin::SetColorRef(VMR9AlphaBitmap& bmpInfo) 00328 { 00329 // Set the COLORREF so that the bitmap outline will be transparent 00330 bmpInfo.clrSrcKey = RGB(255, 255, 255); // Pure white 00331 bmpInfo.dwFlags |= VMRBITMAP_SRCCOLORKEY; 00332 }