HRESULT CMovie::SetAllocatorPresenter( CComPtr<IBaseFilter> filter ) { if( filter == NULL ) { return E_FAIL; } HRESULT hr; CComPtr<IVMRSurfaceAllocatorNotify9> lpIVMRSurfAllocNotify; hr = filter->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, reinterpret_cast<void**>(&lpIVMRSurfAllocNotify)); // create our surface allocator m_Allocator = new CAllocator( m_D3D, m_D3DDev ); m_surfaceAllocator.Attach( m_Allocator ); if( FAILED( hr ) ) { m_surfaceAllocator = NULL; return hr; } // let the allocator and the notify know about each other DWORD_PTR userId = 0xACDCACDC ; hr = lpIVMRSurfAllocNotify->AdviseSurfaceAllocator( userId, m_surfaceAllocator ); hr = m_surfaceAllocator->AdviseNotify(lpIVMRSurfAllocNotify); return hr; }
/* * Class: sage_DShowMediaPlayer * Method: setVideoRendererFilter0 * Signature: (JLjava/lang/String;Ljava/util/Map;)V */ JNIEXPORT void JNICALL Java_sage_DShowMediaPlayer_setVideoRendererFilter0 (JNIEnv *env, jobject jo, jlong dataPtr, jstring jfilterName, jobject jfilterOptions) { if (jfilterName == NULL || env->GetStringLength(jfilterName) == 0 || !dataPtr){return;} CPlayerData* pData = (CPlayerData*) dataPtr; const char* cName = env->GetStringUTFChars(jfilterName, NULL); slog((env, "DShowPlayer setVideoRendererFilter0(%s) called\r\n", cName)); CComPtr<IBaseFilter> pFilter = NULL; HRESULT hr = FindFilterByName(&pFilter, CLSID_LegacyAmFilterCategory, cName); env->ReleaseStringUTFChars(jfilterName, cName); BOOL vmr9Config = FALSE; BOOL evrConfig = FALSE; if (SUCCEEDED(hr) && jfilterOptions) { jint dxvaMode = 0; jint dxvaDeinterlace = 0; GetMapIntValue(env, jfilterOptions, "dxva_mpeg_mode", &dxvaMode); GetMapIntValue(env, jfilterOptions, "force_deinterlace", &dxvaDeinterlace); pData->SetDXVAParameters(dxvaMode, dxvaDeinterlace); jboolean ccOK = JNI_TRUE; GetMapBoolValue(env, jfilterOptions, "enable_cc", &ccOK); if (!ccOK) pData->DisableCC(); // Get the DX9 device pointers, if they don't exist we can't use our custom VMR9 renderer jlong jD3D = 0; jlong jD3DDevice = 0; if (GetMapLongValue(env, jfilterOptions, "d3d_object_ptr", &jD3D) && GetMapLongValue(env, jfilterOptions, "d3d_device_ptr", &jD3DDevice)) { IDirect3D9* pD3D = (IDirect3D9*) jD3D; IDirect3DDevice9* pD3DDevice = (IDirect3DDevice9*) jD3DDevice; // Set the rendering mode and number of streams. CComPtr<IVMRFilterConfig9> pConfig = NULL; // See if it's EVR or VMR hr = pFilter->QueryInterface(IID_IVMRFilterConfig9, (void**)&(pConfig.p)); if (SUCCEEDED(hr)) { slog((env, "Using VMR9 for video rendering\r\n")); hr = pConfig->SetRenderingMode(VMR9Mode_Renderless); PLAYEXCEPT_RET(sage_PlaybackException_DIRECTX_INSTALL); /* * NOTE: If we don't set the number of streams than we don't get the optimal * format types as choices and end up using a private texture when we don't need to. * I think this is because certain features of the * VMR are not available in mixing mode or something like that. * Update: 10/12/2004 - I have now learned that when you put the VMR9 * into mixing mode that it will then use the D3DRenderTarget itself * to do the mixing. I saw a usenet post of the exact VMR9 corruption * problem I was having where the OSD was showing up on the video frame surface. * By not setting the number of streams I keep the VMR9 in Renderless non-mixing mode. * BUT this has the downside of breaking CC support for the VMR9 so we have a registry * setting to allow this. * 10/13/04 - The first problem came back where the format types are wrong. No idea * why this was working fine yesterday. */ if (GetRegistryDword(HKEY_LOCAL_MACHINE, "Software\\Frey Technologies\\SageTV\\DirectX9", "AllowCCForVMR9", 1) && ccOK) { // NOTE: We changed this from 2 to 3 because on Vista you need another input // to handle subpicture blending for DVD playback. And I don't believe there's any // negative to having 3 instead of 2; the big difference is between 1 and 2. hr = pConfig->SetNumberOfStreams(3); // video + CC + subpicture PLAYEXCEPT_RET(sage_PlaybackException_DIRECTX_INSTALL); } else { hr = pConfig->SetNumberOfStreams(1); PLAYEXCEPT_RET(sage_PlaybackException_DIRECTX_INSTALL); } CComPtr<IVMRSurfaceAllocatorNotify9> lpIVMRSurfAllocNotify = NULL; pFilter->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, (void**)&(lpIVMRSurfAllocNotify.p)); // create our surface allocator CVMRAllocator* myVMRAllocator = new CVMRAllocator(hr, pD3D, pD3DDevice); PLAYEXCEPT_RET(sage_PlaybackException_SAGETV_INSTALL); pData->SetVMR9Allocator(myVMRAllocator); // let the allocator and the notify know about each other hr = lpIVMRSurfAllocNotify->AdviseSurfaceAllocator(0xCAFEBABE, myVMRAllocator); HTESTPRINT(hr); hr = myVMRAllocator->AdviseNotify(lpIVMRSurfAllocNotify); HTESTPRINT(hr); hr = S_OK; vmr9Config = TRUE; } else { slog((env, "Using EVR for video render\r\n")); evrConfig = TRUE; hr = S_OK; } } } if (SUCCEEDED(hr)) hr = pData->SetVideoRenderer(pFilter); if (SUCCEEDED(hr) && evrConfig) { // Configure the EVR presenter after we add the EVR to the filter graph jlong jD3DDevMgr = 0; if (GetMapLongValue(env, jfilterOptions, "d3d_device_mgr", &jD3DDevMgr)) { CComPtr<IMFVideoRenderer> lpIMFVideoRenderer = NULL; hr = pFilter->QueryInterface(IID_IMFVideoRenderer, (void**)&(lpIMFVideoRenderer.p)); HTESTPRINT(hr); if (SUCCEEDED(hr)) { // Configure EVR to use our custom presenter CComPtr<IMFVideoPresenter> lpIMFVideoPresenter = NULL; hr = CoCreateInstance(CLSID_CustomEVRPresenter, NULL, CLSCTX_INPROC_SERVER, IID_IMFVideoPresenter, (void**)&(lpIMFVideoPresenter.p)); HTESTPRINT(hr); if (SUCCEEDED(hr)) { // Set the Direct3D device pointer IDirect3DDeviceManager9* pD3DDevMgr = (IDirect3DDeviceManager9*) jD3DDevMgr; ISTVEVRPrstr* pMyEvr = NULL; lpIMFVideoPresenter->QueryInterface(IID_ISTVEVRPrstr, (void**)&pMyEvr); pMyEvr->set_D3DDeviceMgr(pD3DDevMgr); hr = lpIMFVideoRenderer->InitializeRenderer(NULL, lpIMFVideoPresenter); HTESTPRINT(hr); SAFE_RELEASE(pMyEvr); IEVRFilterConfig* pEvrConfig = NULL; hr = pFilter->QueryInterface(IID_IEVRFilterConfig, (void**)&pEvrConfig); HTESTPRINT(hr); // Try three inputs for now; one for video, one for CC and one for subpicture // But only use 3 on Vista by default since we've seen issues w/ it on XP OSVERSIONINFOEX osInfo; ZeroMemory(&osInfo, sizeof(OSVERSIONINFOEX)); osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); DWORD evrInputsDefault = 1; if (GetVersionEx((LPOSVERSIONINFO)&osInfo)) { if (osInfo.dwMajorVersion >= 6) evrInputsDefault = 3; } DWORD evrInputs = GetRegistryDword(HKEY_LOCAL_MACHINE, "Software\\Frey Technologies\\SageTV\\DirectX9", "EVRInputPins", evrInputsDefault); slog((env, "Using %d input pins on the EVR\r\n", (int)evrInputs)); pEvrConfig->SetNumberOfStreams(evrInputs < 1 ? 1 : (evrInputs > 3 ? 3 : evrInputs)); SAFE_RELEASE(pEvrConfig); slog((env, "Finished with EVR configuration OK\r\n")); } } } } else if (SUCCEEDED(hr) && vmr9Config) { IVMRDeinterlaceControl9* pVmrDeint = NULL; hr = pFilter->QueryInterface(IID_IVMRDeinterlaceControl9, (void**)&pVmrDeint); if (SUCCEEDED(hr)) { slog(("Setting up VMR9 deinterlacing\r\n")); hr = pVmrDeint->SetDeinterlacePrefs(DeinterlacePref9_NextBest); HTESTPRINT(hr); /* VMR9VideoDesc VideoDesc; DWORD dwNumModes = 0; AM_MEDIA_TYPE vmrConn; hr = renderInput->ConnectionMediaType(&vmrConn); HTESTPRINT(hr); if (vmrConn.formattype == FORMAT_VideoInfo2) { VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*) vmrConn.pbFormat; // Fill in the VideoDesc structure VideoDesc.dwSize = sizeof(VMR9VideoDesc); VideoDesc.dwSampleWidth = vih2->bmiHeader.biWidth; VideoDesc.dwSampleHeight = vih2->bmiHeader.biHeight; VideoDesc.SampleFormat = ConvertInterlaceFlags(vih2->dwInterlaceFlags); VideoDesc.dwFourCC = vih2->bmiHeader.biCompression; VideoDesc.InputSampleFreq.dwNumerator = 30000; VideoDesc.InputSampleFreq.dwDenominator = 1001; VideoDesc.OutputFrameFreq.dwNumerator = 60000; VideoDesc.OutputFrameFreq.dwDenominator = 1001; hr = pVmrDeint->GetNumberOfDeinterlaceModes(&VideoDesc, &dwNumModes, NULL); HTESTPRINT(hr); if (SUCCEEDED(hr) && (dwNumModes != 0)) { // Allocate an array for the GUIDs that identify the modes. GUID *pModes = new GUID[dwNumModes]; if (pModes) { // Fill the array. hr = pVmrDeint->GetNumberOfDeinterlaceModes(&VideoDesc, &dwNumModes, pModes); if (SUCCEEDED(hr)) { HTESTPRINT(hr); // Loop through each item and get the capabilities. for (DWORD i = 0; i < dwNumModes; i++) { VMR9DeinterlaceCaps Caps; ZeroMemory(&Caps, sizeof(Caps)); Caps.dwSize = sizeof(VMR9DeinterlaceCaps); hr = pVmrDeint->GetDeinterlaceModeCaps(&(pModes[i]), &VideoDesc, &Caps); HTESTPRINT(hr); if (SUCCEEDED(hr)) { if (Caps.DeinterlaceTechnology == DeinterlaceTech9_BOBLineReplicate) slog(("VM9Deinterlacing Tech: BOBLineReplicate\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_BOBVerticalStretch) slog(("VM9Deinterlacing Tech: BOBVerticalStretch\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_MedianFiltering) slog(("VM9Deinterlacing Tech: MedianFiltering\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_EdgeFiltering) slog(("VM9Deinterlacing Tech: EdgeFiltering\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_FieldAdaptive) slog(("VM9Deinterlacing Tech: FieldAdaptive\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_PixelAdaptive) slog(("VM9Deinterlacing Tech: PixelAdaptive\r\n")); else if (Caps.DeinterlaceTechnology == DeinterlaceTech9_MotionVectorSteered) slog(("VM9Deinterlacing Tech: MotionVectorSteered\r\n")); else slog(("VM9Deinterlacing Tech: Proprietary...\r\n")); } } if (dwNumModes) { // hr = pVmrDeint->SetDeinterlaceMode(0, pModes); // HTESTPRINT(hr); } } delete [] pModes; } } FreeMediaType(vmrConn); } GUID realDeint; hr = pVmrDeint->GetActualDeinterlaceMode(0, &realDeint); LPOLESTR psz; StringFromCLSID(realDeint, &psz); char conv[64]; WideCharToMultiByte(CP_ACP, 0, psz, -1, conv, 64, 0, 0); CoTaskMemFree(psz); slog(("Actual deinterlace: hr=0x%x guid=%s\r\n", hr, conv)); GUID setDeint; hr = pVmrDeint->GetDeinterlaceMode(0, &setDeint); StringFromCLSID(setDeint, &psz); WideCharToMultiByte(CP_ACP, 0, psz, -1, conv, 64, 0, 0); CoTaskMemFree(psz); slog(("deinterlace mode: hr=0x%x guid=%s\r\n", hr, conv)); if (hr == S_FALSE) { slog(("Setting deinterlace mode to actual mode...\r\n")); hr = pVmrDeint->SetDeinterlaceMode(0, &realDeint); hr = pVmrDeint->GetDeinterlaceMode(0, &setDeint); StringFromCLSID(setDeint, &psz); WideCharToMultiByte(CP_ACP, 0, psz, -1, conv, 64, 0, 0); CoTaskMemFree(psz); slog(("deinterlace mode: hr=0x%x guid=%s\r\n", hr, conv)); } */ pVmrDeint->Release(); } DWORD vmrMixMode = GetRegistryDword(HKEY_LOCAL_MACHINE, "Software\\Frey Technologies\\SageTV\\DirectX9", "YUVMixing", 1); if (vmrMixMode) { IVMRMixerControl9* vmrMix = NULL; hr = pFilter->QueryInterface(IID_IVMRMixerControl9, (void**)&vmrMix); if (SUCCEEDED(hr)) { DWORD currPrefs = 0; hr = vmrMix->GetMixingPrefs(&currPrefs); slog((env, "Curr Mix Prefs=0x%x\r\n", currPrefs)); currPrefs &= ~MixerPref9_RenderTargetMask; currPrefs |= MixerPref9_RenderTargetYUV; hr = vmrMix->SetMixingPrefs(currPrefs); vmrMixMode = currPrefs; vmrMix->GetMixingPrefs(&currPrefs); slog((env, "Set to 0x%x, hr=0x%x, New Mix Prefs=0x%x\r\n", vmrMixMode, hr, currPrefs)); vmrMix->Release(); } else HTESTPRINT(hr); } } if (FAILED(hr)) { elog((env, "Could not add specified video rendering filter to graph hr=0x%x\r\n", hr)); } }